- 题面描述
- 在秦腾进入北京大学学习的第一个学期,就不幸遇到了前所未有的教学评估。在教学评估期间,同学们被要求八点起床,十一点回宿舍睡觉,不准旷课,上课不准迟到,上课不准睡觉……甚至连著名的北大三角地也在教学评估期间被以影响校容的理由被拆除。这些“变态”规定令习惯了自由自在随性生活学习的北大同学叫苦不迭。这一天又到了星期五,一大早就是秦腾最不喜欢的高等代数课。可是因为是教学评估时期,不能迟到,于是他在八点五分的时候挣扎着爬出了宿舍,希望能赶快混进在八点钟已经上课了的教室。可是,刚一出宿舍楼门他就傻眼了:从宿舍到教学楼的路上已经站满了教学评估团的成员。他们的目的就是抓住像他这样迟到的学生,扣除学校的分数。秦腾当然不能让评估团得逞。他经过观察发现,整个评估团分成了\(N\)个小组,每个小组的成员都分布在从宿舍楼到教学楼的路上的某一段,并且同一小组的成员间的距离是相等的。于是,我们可以用三个整数\(S,E,D\)来描述评估团的小组:既该小组的成员在从宿舍到教学楼的路上的:\(S,S+D,S+2D,…,S+KD(K∈Z,S+KD≤E,S+(K+1)D>E)\)位置。观察到了教学评估团的这一特点,又经过了认真的思考,秦腾想出了对策:如果在路上的某一位置有奇数个教学评估团成员,他就可以运用调虎离山,声东击西,隔山打牛,暗度陈仓……等方法,以这一地点为突破口到达教学楼。但是由于教学评估团的成员的十分狡猾,成员位置安排的设计极其精妙,导致在整条路上几乎没有这样的位置出现。即使由于安排不慎重出现了这样的位置,最多也仅有一个。现在秦腾观察出了所有小组的安排,但是由于整个教学评估团的人数太多,他实在看不出这样的位置是否存在。现在,你的任务是写一个程序,帮助他做出判断。
- 输入格式
- 第一行为T代表测试数据组数每组第一行为\(N\)。接下来\(N\)行,每行三个整数\(S_i,E_i,D_i\)。\(N\leq 2*10^5,0\leq S_i,E_i,D_i\leq 2^{31}-1\) 输入文件不大于\(2048K\)
- 输出格式
- 对于每组数据如果所求位置不存在,则输出
Poor Qin Teng:(
- 否则输出两个整数\(Pos_i,Count\),代表在唯一位置\(Pos_i\),有\(Count\)个教学评估图的成员\(Count\)为奇数,注意输出的所有符号为英文半号
- 题解
- 二分好题。注意到题目中有一个看似无用却有大用的条件,奇数个人的点至多一个。利用这个条件不难发现当将数轴上所有点取前缀和后前缀和的奇偶性必然是 先是一段偶数,再是一段奇数,而其变化点即是题目所求。故使用二分。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
struct rec{
int l,r,d;
} a[MAXN];
int T,n,ans,cnt;
int calc(int pos){
int ret=0;
for (int i=1;i<=n;i++){
if (a[i].l<=pos){
ret+=(min(a[i].r,pos)-a[i].l)/a[i].d+1;
}
}
return ret;
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%d",&n);
int mx=0;
for (int i=1;i<=n;i++){
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].d);
mx=max(mx,a[i].r);
}
int l=0,r=mx,mid;
while (l+1<r){
mid=((ll)l+(ll)r)>>1ll;
if (calc(mid)&1) r=mid;
else l=mid;
}
ans=r; cnt=0;
for (int i=1;i<=n;i++){
if (a[i].l>r||a[i].r<r) continue;
if ((r-a[i].l)%a[i].d==0) cnt++;
}
if (cnt&1) printf("%d %d\n",ans,cnt);
else printf("Poor QIN Teng:(\n");
}
return 0;
}