转载请注明出处:http://blog.csdn.net/jiangshibiao/article/details/21479405
【题目】在秦腾进入北京大学学习的第一个学期,就不幸遇到了前所未有的教学评估。在教学评估期间,同学们被要求八点起床,十一点回宿舍睡觉,不 准旷课,上课不准迟到,上课不准睡觉……甚至连著名的北大三角地也在教学评估期间被以影响校容的理由被拆除。这些“变态”规定令习惯了自由自在随性生活学 习的北大同学叫苦不迭。这一天又到了星期五,一大早就是秦腾最不喜欢的高等代数课。可是因为是教学评估时期,不能迟到,于是他在八点五分的 时候挣扎着爬出了宿舍,希望能赶快混进在八点钟已经上课了的教室。可是,刚一出宿舍楼门他就傻眼了: 从宿舍到教学楼的路上已经站满了教学评估团的成员。他们的目的就是抓住像他这样迟到的学生,扣除学校的分数。秦腾当然不能让评估团得逞。他经过观察发现,整个评估团分成了N个小组,每个小组的成员都分布在从宿舍楼到教学楼的路上的某一段,并且同一小组的成员间的距离是相等的。于是,我们可以用三个整数S, E, D来描述评估团的小组: 既该小组的成员在从宿舍到教学楼的路上的:S, S + D, S + 2D, …, S + KD (K ∈ Z, S + KD ≤ E, S + (K + 1)D > E)位置。观 察到了教学评估团的这一特点,又经过了认真的思考,秦腾想出了对策: 如果在路上的某一位置有奇数个教学评估团成员,他就可以运用调虎离山,声东击西,隔山打牛,暗度陈仓……等方法,以这一地点为突破口到达教学楼。但是由于 教学评估团的成员的十分狡猾,成员位置安排的设计极其精妙,导致在整条路上几乎没有这样的位置出现。即使由于安排不慎重出现了这样的位置,最多也仅有一 个。现在秦腾观察出了所有小组的安排,但是由于整个教学评估团的人数太多,他实在看不出这样的位置是否存在。现在,你的任务是写一个程序,帮助他做出判 断。
输入对于每个测试数据,如果题目中所求的位置不存在,既任意位置都有偶数个教学评估团的成员存在,在输出文件的中打印一行:"Poor QIN Teng:(" (不包含引号)否则打印两个整数Posi, Count,代表在唯一的位置Posi,有Count个教学评估团的成员。根据题意,Count应为奇数。
样例输入
3
2
1 10 1
2 10 1
2
1 10 1
1 10 1
4
1 10 1
4 4 1
1 5 1
6 10 1
样例输出
1 1
Poor QIN Teng:(
4 3
提示
教学评估团的总人数不大于10^8
Si ≤ Ei
1 ≤ T ≤ 5
N ≤ 200000
0 ≤ Si, Ei, Di ≤ 2^31 – 1
输入文件的大小不大于2048KB
【分析】利用奇数最多就一个的限制,我们可以二分答案假验证。显然,如果坐标0到当前枚举到的坐标ans间有奇数个人,那么那个奇数点一定在这中间。然后再迭代验证。注意要用int64来二分。
【代码】
#include<cstdio> using namespace std; typedef long long big; const big INF=2147483647; const int maxn=200005; int test,n,i; big s[maxn],e[maxn],d[maxn],ans,max; inline bool check(big now) { big count=0; for (int i=1;i<=n;i++) if (s[i]<=now) { if (e[i]<=now) count+=(e[i]-s[i])/d[i]+1; else count+=(now-s[i])/d[i]+1; } if (count%2==0) return false; return true; } inline big erfen(big l,big r) { if (l==r) return l; big mid=(l+r)/2; if (check(mid)) return erfen(l,mid); return erfen(mid+1,r); } inline void print() { big count=0; for (int i=1;i<=n;i++) if ((s[i]<=ans)&&(ans<=e[i])&&((ans-s[i])%d[i]==0)) count++; if (count%2==0) printf("Poor QIN Teng:(");else printf("%lld %lld",ans,count); printf("\n"); } int main() { scanf("%d",&test); while (test) { test--; scanf("%d",&n); for (i=1;i<=n;i++) { scanf("%lld%lld%lld",&s[i],&e[i],&d[i]); if (e[i]>max) max=e[i]; } ans=erfen(0,max); print(); } return 0; }