思路:
"题目保证给的测试数据要么没有奇数的,要么只有一个是奇数个传单." 我们二分枚举1--2^31,对于mid,算出0--mid一共发出去tmp张传单,如果tmp是偶数那么奇数的那个人一定不会在前面,因为只有一个奇数,其他的都是偶数,当前的数是不是偶数就能断定奇数的那个人在不在mid前面.对于不存在的这个判定,我是前直接跑出所有的个数,也就是求出范围INF以前的所有,如果偶数那么就不存在,否则就二分找,找到后在枚举这个找到的人有多少个传单,输出来就行了.这个只是用二分的特性去节省时间,和以往的二分不同,因为他不是在单调函数上查找的.
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; struct node { __int64 s,e,k; }num[21000]; int main() { int n,i,j; while(~scanf("%d",&n)) { __int64 sum=0,Max=-1; for(i=1;i<=n;i++) { scanf("%I64d%I64d%I64d",&num[i].s,&num[i].e,&num[i].k); sum+=(num[i].e-num[i].s)/num[i].k+1; if(num[i].e>Max) Max=num[i].e; } if(sum%2==0) printf("DC Qiang is unhappy.\n"); else { __int64 left=0,mid,right=Max; while(left<right) { mid=(left+right)/2; __int64 t=0; for(i=1;i<=n;i++) { if(mid>=num[i].e) t+=(num[i].e-num[i].s)/num[i].k+1; else if(mid<num[i].s) continue; else t+=(mid-num[i].s)/num[i].k+1; } if(t%2==0) left=mid+1; else right=mid; } //printf("%I64d ",mid); mid=right; __int64 t=0; for(i=1;i<=n;i++) { if(mid>=num[i].s&&mid<=num[i].e&&(mid-num[i].s)%num[i].k==0) t++; } printf("%I64d %I64d\n",mid,t); } } return 0; }