洛谷传送门
解析
因为至多有一个单数
假设其位置为k,1-i的累加和为s[i]
则s[1]-s[k-1]全是偶数
s[k]-s[max]全是奇数
答案呈单调性,可以用二分算法
check函数(计算前缀和)也很容易用O(n)写出:
long long check(int x){long long tot=0;for(int i=1;i<=n;i++){if(p[i].b<=x){tot += (p[i].b-p[i].a)/p[i].m+1;}else if(p[i].a>x) continue;else{tot += (x-p[i].a)/p[i].m+1;}}return tot;
}
(时间复杂度应该可以更优,但这样够了,大脑就不想动了。。。)
两个地方要加1,因为排头有一个,之后的个数这是长度除间隔的地板除法
然后二分枚举位置判断奇偶即可
PS:不开longlong见祖宗
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<vector>
using namespace std;
const int M=1e9;
long long n,t;
long long mx=0;
struct node{long long a,b,m;
}p[200500];
long long check(int x){long long tot=0;for(int i=1;i<=n;i++){if(p[i].b<=x){tot += (p[i].b-p[i].a)/p[i].m+1;}else if(p[i].a>x) continue;else{tot += (x-p[i].a)/p[i].m+1;}}return tot;
}
int main(){scanf("%lld",&t);for(int k=1;k<=t;k++){mx=0;scanf("%lld",&n); for(int i=1;i<=n;i++){scanf("%lld%lld%lld",&p[i].a,&p[i].b,&p[i].m);mx=max(mx,p[i].b);}long long st=0,ed=mx+1;while(st<ed){long long mid=(st+ed) >> 1;if(check(mid)%2==1) ed=mid;else st=mid+1;}if(st==mx+1){//返回mx+1,说明全是偶数,无懈可击printf("Poor QIN Teng:( \n");continue;}printf("%lld %lld\n",st,check(st)-check(st-1));}return 0;
}