题目链接: 传送门
Flyer
Time Limit: 1000MS Memory Limit: 32768 K
Time Limit: 1000MS Memory Limit: 32768 K
Description
The new semester begins! Different kinds of student societies are all trying to advertise themselves, by giving flyers to the students for introducing the society. However, due to the fund shortage, the flyers of a society can only be distributed to a part of the students. There are too many, too many students in our university, labeled from 1 to 2^32. And there are totally N student societies, where the i-th society will deliver flyers to the students with label A_i, A_i+C_i,A_i+2C_i,…A_i+kC_i (A_i+kC_i<=B_i, A_i+(k+1)C_i>B_i). We call a student "unlucky" if he/she gets odd pieces of flyers. Unfortunately, not everyone is lucky. Yet, no worries; there is at most one student who is unlucky. Could you help us find out who the unfortunate dude (if any) is? So that we can comfort him by treating him to a big meal!
Input
There are multiple test cases. For each test case, the first line contains a number N (0 < N <= 20000) indicating the number of societies. Then for each of the following N lines, there are three non-negative integers A_i, B_i, C_i (smaller than 2^31, A_i <= B_i) as stated above. Your program should proceed to the end of the file.
Output
For each test case, if there is no unlucky student, print "DC Qiang is unhappy." (excluding the quotation mark), in a single line. Otherwise print two integers, i.e., the label of the unlucky student and the number of flyers he/she gets, in a single line.
Sample Input
2
1 10 1
2 10 1
4
5 20 7
6 14 3
5 9 1
7 21 12
Sample Output
1 1
8 1
解题思路:
有n个社团,第i个社团有3个数a[i] b[i] c[i] 每个社团给学号小于等于b[i]且为a[i],a[i]+c[i]..a[i]+k*c[i]的人发传单。最多只有一个人被发到奇数次传单,求出他的编号和传单数目。如果没人,就输出 DC Qiang is unhappy.。
如果有人收到奇数次传单,则所有社团发传单的总数显然是奇数。所以我们二分枚举传单总数。每次对于二分的结果mid检查学号[0,mid]区间内收到的传单总数是不是奇数。 如果是,那结果肯定在[0,mid]内,否则就在[mid+1,2^31]内,继续二分。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef __int64 LL;
const long long INF = (1LL << 31);
struct node{
LL a,b,c;
};
node p[20005];
int N;
bool OK(LL x)
{
LL sum = 0,tmp = 0;
for (int i = 0;i < N;i++)
{
tmp = min(x,p[i].b);
if (tmp >= p[i].a)
{
sum += (tmp - p[i].a)/p[i].c + 1;
}
}
if (sum & 1)
return true;
else
return false;
}
int main()
{
while (~scanf("%d",&N))
{
LL maxx = 0,minn = INF,sum = 0;
memset(p,0,sizeof(p));
for (int i = 0;i < N;i++)
{
scanf("%I64d%I64d%I64d",&p[i].a,&p[i].b,&p[i].c);
maxx = max(maxx,p[i].b);
minn = min(minn,p[i].a);
sum += (p[i].b - p[i].a)/p[i].c + 1;
}
//cout << minn << " " << maxx << endl;
if (!(sum & 1))
{
printf("DC Qiang is unhappy.
");
continue;
}
LL left = minn,right = maxx;
while (left < right)
{
LL mid = left +((right-left)>>1);
if (OK(mid))
{
right = mid;
}
else
{
left = mid + 1;
}
}
//cout << left << " " << right << endl;
LL cnt = 0;
for (int i = 0;i < N;i++)
{
if (right >= p[i].a && right <= p[i].b && (right - p[i].a) % p[i].c == 0)
{
cnt++;
}
}
printf("%I64d %I64d
",right,cnt);
}
return 0;
}