最大化最小值
POJ 3258: River Hopscotch
同noip跳石头。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
同noip跳石头。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=50000+5;
const int INF=0x3f3f3f3f;
int a[maxn],l,n,m;
bool check(int mid){
int sum=0,dis=0;
for(int i=2;i<=n;i++){
dis+=a[i]-a[i-1];
if(dis<mid)sum++;
else dis=0;
}
return sum<=m;
}
int main() {
ios::sync_with_stdio(false);
//freopen("River Hopscotch.in","r",stdin);
cin>>l>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
a[++n]=0,a[++n]=l;
sort(a+1,a+n+1);
// for(int i=1;i<=n;i++) D(a[i]);
int l=0,r=INF;
while(l<r){
// D(l);D(r);E;
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l;
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3273: Monthly Expense
最小化最大值。
从左往右check即可。预处理前缀和简化运算。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
最小化最大值。
从左往右check即可。预处理前缀和简化运算。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100000+5;
const int INF=0x3f3f3f3f;
int n,m,a[maxn],sum[maxn],maxa=0;
bool check(int mid){
// if(mid<maxa) return false;
int ans=1,last=0;
// D(mid);E;
for(int i=1;i<=n;i++){
if(a[i]>mid) return false; //注意这里要特判
int expense=sum[i]-sum[last];
// D(expense);E;
if(expense>mid){
ans++;last=i-1;
}
}
// D(ans);E;
return ans<=m;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Monthly Expense.in","r",stdin);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i],sum[i]=sum[i-1]+a[i];
maxa=max(maxa,a[i]);
}
// check(100);
int l=0,r=INF;
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<r;
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3104: Drying
不开long long会WA(原因未知),用了cin会TLE。(这两个坑坑了了我五六次提交)
剩下就很简单了,二分时间然后check吹风机使用的总时间是否<=mid即可。
具体地说,对于二分值mid,如果衣服i的含水量<=mid,则不用操作。
如果衣服i的含水量>mid,则设吹风机对衣服i吹了x秒。
则x满足不等式kx+(mid-x)>=a[i],即x>=(a[i]-mid)/(k-1)。
也就是说,对于衣服i,需要吹ceil((a[i]-mid)/(k-1))秒。
ps:注意这里k-1可能为0,所以要特判k=1的情况。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
不开long long会WA(原因未知),用了cin会TLE。(这两个坑坑了了我五六次提交)
剩下就很简单了,二分时间然后check吹风机使用的总时间是否<=mid即可。
具体地说,对于二分值mid,如果衣服i的含水量<=mid,则不用操作。
如果衣服i的含水量>mid,则设吹风机对衣服i吹了x秒。
则x满足不等式kx+(mid-x)>=a[i],即x>=(a[i]-mid)/(k-1)。
也就是说,对于衣服i,需要吹ceil((a[i]-mid)/(k-1))秒。
ps:注意这里k-1可能为0,所以要特判k=1的情况。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100000+5;
const int INF=0x3f3f3f3f;
ll n,a[maxn],k,maxa=0;
bool check(int mid){
ll ans=0;
for(int i=1;i<=n;i++){
if(a[i]<=mid) continue;
if((a[i]-mid)%(k-1)==0) ans+=(a[i]-mid)/(k-1);
else ans+=(a[i]-mid)/(k-1)+1;
}
return ans<=mid;
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Drying.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),maxa=max(maxa,a[i]);
cin>>k;
if(k==1){
cout<<maxa;return 0;
}
ll l=0,r=INF;
while(l<r){
ll mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<r;
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3045: Cow Acrobats
题解链接 https://www.cnblogs.com/wmrv587/p/3700452.html
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
https://www.cnblogs.com/wmrv587/p/3700452.html
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=50000+5;
const int INF=0x3f3f3f3f;
struct node{
int w,s;
bool operator<(const node& h)const{return w+s<h.w+h.s;}
}a[maxn];
int n,W=0,ans=-INF;
int main() {
ios::sync_with_stdio(false);
//freopen("Cow Acrobats.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].w>>a[i].s;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
ans=max(ans,W-a[i].s);
W+=a[i].w;
// D(W);
}
cout<<ans;
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
01分数规划
POJ 2976: Dropping tests
设答案为mid,二分答案。
具体check过程如下:
,则
即,只要对
排序后,取较大的n-k个,判断和是否大于等于0即可。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
设答案为mid,二分答案。
具体check过程如下:
∑ai/∑bi>=mid,则∑ai-mid*∑bi>=0
即∑(ai-mid*bi)>=0,只要对ai-mid*bi排序后,取较大的n-k个,判断和是否大于等于0即可。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=1000+5;
const int INF=0x3f3f3f3f;
const double eps=1e-5;
int n,k;
double a[maxn],b[maxn],c[maxn];
bool check(double mid){
for(int i=1;i<=n;i++) c[i]=a[i]-mid*b[i];
sort(c+1,c+n+1);
double sum=0;
for(int i=k+1;i<=n;i++) sum+=c[i];
return sum>=0;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Dropping tests.in","r",stdin);
while(cin>>n>>k){
if(n==0&&k==0) break;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
double l=0,r=1;//ai<=bi
while(r-l>eps){
double mid=(r+l)/2;
if(check(mid)) l=mid;
else r=mid;
}
cout<<(int)((l+0.005)*100)<<endl; //题目要求精确到0.001并四舍五入
}
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3111: K Best
方法同Dropping tests。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
方法同Dropping tests。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100000+5;
const int INF=0x3f3f3f3f;
const double eps=1e-5;
int n,k;
struct node{
double v,w,c;
int id;
bool operator<(const node& h)const{return c>h.c;}
}a[maxn],b[maxn];
bool check(double mid) {
for(int i=1; i<=n; i++) b[i].c=a[i].v-mid*a[i].w,b[i].id=a[i].id;
sort(b+1,b+n+1);
double sum=0;
for(int i=1; i<=k; i++){
sum+=b[i].c;
}
return sum>=0;
}
int main() {
// ios::sync_with_stdio(false);
//freopen("K Best.in","r",stdin);
cin>>n>>k;
for(int i=1; i<=n; i++) scanf("%lf%lf",&a[i].v,&a[i].w),a[i].id=i;
double l=0,r=INF;
while(r-l>eps) {
double mid=(r+l)/2;
// D(l);D(r);D(mid);E;
if(check(mid)) l=mid;
else r=mid;
}
for(int i=1;i<=k;i++) printf("%d ",b[i].id);
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
第k大值
POJ 3579: Median
二分答案,然后用upper_bound来求绝对值差在mid以内的数对的个数即可。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
二分答案,然后用upper_bound来求绝对值差在mid以内的数对的个数即可。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100000+5;
const int INF=0x3f3f3f3f;
int n,a[maxn],ans,l,r;
ll m;
ll check(int mid){ //返回绝对值差在mid以内的数对的个数
ll sum=0;
for(int i=1;i<=n;i++){
sum+=(ll)(upper_bound(a+i+1,a+n+1,a[i]+mid)-(a+i+1));
// D(l);D(r);D(i);D(mid);D(sum);E;
}
return sum;
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Median.in","r",stdin);
while(cin>>n){
m=(ll)n*(n-1)/2;
for(int i=1;i<=n;i++) scanf("%d",&a[i]); //cin会TLE
sort(a+1,a+n+1);
l=0,r=INF;
while(l<r){
int mid=l+r>>1;
if(check(mid)>=(m+1)/2) r=mid;
else l=mid+1;
/*
//不能这样写 反例
4
2 2 4 5
int mid=l+r+1>>1;
if(check(mid)<=(m+1)/2) l=mid;
else r=mid-1;
*/
}
cout<<r<<endl;
}
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3685: Matrix
观察这个式子,可以发现j不变的情况下,随着i的增大,Aij也相应增大。
由这个受到启发:二分枚举第M小的数,然后按列寻找,找到第一个大于这个数的位置,就可以知道该列中有多少个数是大于这个数。
难点是二分范围和精度问题,因为用int结果WA无数次,最后一个个换掉,最后全部变成long long才过。
代码如下
/*
*/
#define method_2
#ifdef method_1
/*
打表用
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100+5;
const int INF=0x3f3f3f3f;
int n=15,a[maxn][maxn];
int main() {
ios::sync_with_stdio(false);
freopen("Matrix.in","r",stdin);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=i*i+100000*i+j*j-100000*j+i*j;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[i][j]<<" ";
}
E;
}
return 0;
}
#endif
#ifdef method_2
/*
观察这个式子,可以发现j不变的情况下,随着i的增大,Aij也相应增大。
由这个受到启发:二分枚举第M小的数,然后按列寻找,找到第一个大于这个数的位置,就可以知道该列中有多少个数是大于这个数。
难点是二分范围和精度问题,因为用int结果WA无数次,最后一个个换掉,最后全部变成long long才过。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100+5;
const ll INF=0x3f3f3f3f3f3f3f3fll;
ll n,T;
ll m;
ll cal(ll i,ll j){
return i*i+100000*i+j*j-100000*j+i*j;
}
/*
ll check(ll now){ //求矩阵中有多少数字小于等于mid
ll sum=0;
for(int i=1;i<=n;i++){ //枚举列
int l=0,r=n+1;
while(l<r){
int mid=l+r>>1;
if(cal(mid,i)>=now) r=mid;
else l=mid+1;
}
sum+=r;
}
return sum;
}
*/
ll check(ll now){ //求矩阵中有多少数字小于mid
ll sum=0;
for(ll i=1;i<=n;i++){ //枚举列
ll l=1,r=n+1;
while(l<r){
ll mid=l+r>>1;
if(cal(mid,i)>now) r=mid;
else l=mid+1;
}
sum+=l-1;
}
return sum;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Matrix.in","r",stdin);
cin>>T;
while(T--){
cin>>n>>m;
// ll l=-100000ll*n,r=n*n+100000ll*n+n*n+n*n; //用这个紧的范围 耗时为[-INF,INF]的一半
ll l=-INF,r=INF;
while(l<r){
/*
ll mid=l+r>>1;
if(check(mid)>=m) r=mid;
else l=mid+1;
*/
ll mid=l+r>>1;
if(check(mid)<m) l=mid+1;
else r=mid;
}
cout<<l<<endl;
}
return 0;
}
#endif
#ifdef method_3
/*
*/
#endif
最小化第k大值
POJ 2010: Moo University - Financial Aid
题解链接 https://www.jianshu.com/p/5765513ce5b4
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
将所有奶牛按照score升序排序后,从大向小一次尝试作为中位数是否可行即可。
为了提高对于每头奶牛判断的效率,用sum1[i]表示i左侧c/2头牛的最小aid和,可用一个大小固定为n/2的大根堆来求,每次与堆顶元素比较。
同理可以对称的定义sum2[i]。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=100000+5;
const int INF=0x3f3f3f3f;
int n,c,f,sum1[maxn],sum2[maxn];//sum1[i]表示i左侧c/2头牛的最小aid和 用一个大小固定为n/2的大根堆来求 每次与堆顶元素比较
struct node{
int s,aid;
bool operator<(const node& h)const{return s<h.s;}
}cow[maxn];
priority_queue<int>q;
void pre1(){
while(q.size()) q.pop();
int sum=0,nowf; //堆中所有元素和
for(int i=1;i<=c;i++){
sum1[i]=sum;
if(q.size()) nowf=q.top();
if(q.size()<n/2){
q.push(cow[i].aid);
sum+=cow[i].aid;
}
else{
if(cow[i].aid<nowf){
q.pop();
q.push(cow[i].aid);
sum=sum-nowf+cow[i].aid;
}
}
// D(sum1[i]);
}
}
void pre2(){
while(q.size()) q.pop();
int sum=0,nowf; //堆中所有元素和
for(int i=c;i>=1;i--){
sum2[i]=sum;
if(q.size()) nowf=q.top();
if(q.size()<n/2){
q.push(cow[i].aid);
sum+=cow[i].aid;
}
else{
if(cow[i].aid<nowf){
q.pop();
q.push(cow[i].aid);
sum=sum-nowf+cow[i].aid;
}
}
// D(sum2[i]);
}
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Moo University - Financial Aid.in","r",stdin);
scanf("%d%d%d",&n,&c,&f);
for(int i=1;i<=c;i++) scanf("%d%d",&cow[i].s,&cow[i].aid);
sort(cow+1,cow+c+1);
pre1();
pre2();
bool flag=false;
for(int i=c-n/2;i>=n/2+1;i--){ //从大到小依次枚举当前值能否作为中位数
if(cow[i].aid+sum1[i]+sum2[i]<=f){
flag=true;
cout<<cow[i].s;
break;
}
}
if(flag==false) cout<<-1;
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3662: Telephone Lines
二分答案,设当前答案为mid。
将所有边的边权-mid后,权值<=0的边边权设为0,否则为1。
然后,从1到n跑最短路,如果最短路<=k,则满足条件。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
二分答案,设当前答案为mid。
将所有边的边权-mid后,权值<=0的边边权设为0,否则为1。
然后,从1到n跑最短路,如果最短路<=k,则满足条件。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=1000+5;
const int maxp=10000+5;
const int INF=0x3f3f3f3f;
int n,p,k,head[maxn],tot=1,vis[maxn];
deque<pii>q;
struct node{
int from,to,c;
}edge[maxp<<1],edge1[maxp<<1];
void add(int from,int to,int c){
edge[++tot].from=head[from],edge[tot].to=to,edge[tot].c=c;
edge1[tot].from=head[from],edge1[tot].to=to;
head[from]=tot;
}
void init(){
while(q.size()) q.pop_front();
q.push_back(make_pair(1,0));
memset(vis,0,sizeof(vis));
}
int bfs(){
init();
while(q.size()){
pii now=q.front();q.pop_front();
int x=now.first,d=now.second;
if(x==n) return d;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=edge1[i].from){
int y=edge1[i].to,c=edge1[i].c;
if(c==0) q.push_front(make_pair(y,d));
else q.push_back(make_pair(y,d+1));
}
}
return INF;
}
bool check(int mid){
for(int i=2;i<=2*p+1;i++){
edge1[i].c=edge[i].c-mid;
if(edge1[i].c<=0) edge1[i].c=0;
else edge1[i].c=1;
}
return bfs()<=k;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Telephone Lines.in","r",stdin);
cin>>n>>p>>k;
int from,to,c;
for(int i=1;i<=p;i++) cin>>from>>to>>c,add(from,to,c),add(to,from,c);
// D(tot);
int l=0,r=INF;
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
r==INF?cout<<-1:cout<<r;
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
其他二分搜索
POJ 1759: Garland
因此可以根据和
递推。
又因为递推式关于单调递增,所以
越小,答案就越小,所以二分
即可。
注意天坑:n=3时,答案是-0.00,要纠正为0.00。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
h_i=2*h_i-1-h_i-2+2
因此可以根据h1和h2递推。
又因为递推式关于hi-1单调递增,所以h_2越小,答案就越小,所以二分h2即可。
注意天坑:n=3时,答案是-0.00,要纠正为0.00。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=1000+5;
const int INF=0x3f3f3f3f;
const double eps=1e-5;
int n;
double A;
double cal(double mid){ //计算B
double pre1=A,pre2=mid,temp;
for(int i=3;i<=n;i++){
temp=2*pre2-pre1+2;
pre1=pre2;pre2=temp;
}
return temp;
}
bool check(double mid){
double pre1=A,pre2=mid,temp;
for(int i=3;i<=n;i++){
temp=2*pre2-pre1+2;
if(temp<0) return false;
pre1=pre2;pre2=temp;
}
return true;
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Garland.in","r",stdin);
cin>>n>>A;
double l=0.0,r=(double)INF;
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
double ans=cal(l);
if(ans<eps) ans=0.00; //天坑 n=3时 答案是-0.00 要纠正为0.00
printf("%.2lf",ans);
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif
POJ 3484: Showstopper
原理同防线。
由于只有一个点有奇数个数,则如果某个点的前缀和为奇数,
这个位置一定在左边,否则在右边,二分位置即可。
注意输入很恶心。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
原理同防线。
由于只有一个点有奇数个数,则如果某个点的前缀和为奇数,
这个位置一定在左边,否则在右边,二分位置即可。
注意输入很恶心。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<string>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn=20000+5; //poj上有人手测出的二分范围
const int maxp=100+5;
const ll INF=0x3f3f3f3f3f3f3f3fll;
char a[maxn];
int n;
vector<ll>x,y,z;
bool read(){
bool flag=false;
x.clear();y.clear();z.clear();
while(gets(a)){
if(strlen(a)==0){
if(flag==true) break;
else continue;
}
ll xx,yy,zz;
sscanf(a,"%lld%lld%lld",&xx,&yy,&zz);
flag=true;
x.push_back(xx);y.push_back(yy);z.push_back(zz);
}
n=x.size();
return flag;
}
ll check(ll mid){ //求1~mid的前缀和
ll ans=0;
for(int i=0;i<n;i++){
if(x[i]>mid) continue;
ans+=(min(y[i],mid)-x[i])/z[i]+1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Showstopper.in","r",stdin);
while(read()){
ll l=0,r=INF;
while(l<r){
ll mid=l+r>>1;
if(check(mid)&1) r=mid;
else l=mid+1;
}
if(r==INF) cout<<"no corruption"<<endl;
else{
cout<<r<<" ";
int tot=0;
for(int i=0;i<n;i++){
if(r<=y[i]&&r>=x[i]){
if((r-x[i])%z[i]==0) tot++;
}
}
cout<<tot<<endl;
}
}
return 0;
}
#endif
#ifdef method_2
/*
*/
#endif
#ifdef method_3
/*
*/
#endif












网友评论