【YBT高效进阶】1基础算法/3二分算法/2防具布置
内存限制:64 MiB
时间限制:1000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
题目描述
现在有N组防具。 我们可以认为防线是一维的,那么每一组防具都分布在防线的某一段上,并且同一组防具是等距离排列的。 也就是说,我们可以用三个整数S,E,D来描述一组防具,即这一组防具布置在防线的S,S+D,S+2D,……,S+kD(k<=z,S+kD<=E,S+(k+1)D>E)位置上。 若一个位置上的防具数量为奇数,则我们称这个位置有破绽,但是整个防线上有且仅有一个位置有破绽或根本没有破绽。请你求出破绽的位置,或是确定防线没有破绽。
输入格式
第一行是一个整数T ,表示有T组互相独立的测试数据。
每组数据的第一行是一个整数N 。
之后N 行,每行三个整数Si Ei,Di代表第i组防具的三个参数,数据用空格隔开。
输出格式
对于每组测试数据,如果防线没有破绽,输出一行 “There’s no weakness.”。
否则在一行内输出两个空格分隔的整数P和 C,表示在位置 P有C 个防具。当然 C 应该是奇数。
样例
样例输入
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
There's no weakness.
4 3
数据范围与提示
对于 100% 的数据1<=T<+5,1<=n<=2*105,0<=si,ei,di<231防具总数不多于 108。
思路
设sum(i)表示0~i的位置上一共的防具数。
若sum(2^31-1),没有破绽
若mid奇数:ans<=mid;r=mid;
若mid偶数:ans>mid;l=mid+1;
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int s[200010],e[200010],d[200010],n;
int sum(int x)
{
int ans=0,i;
for(i=1;i<=n;i++)
if(s[i]<=x)
ans+=(min(x,e[i])-s[i])/d[i]+1;
return ans;
}
int main()
{
long long T,i,l,r,mid;
ios::sync_with_stdio(false);
for(cin>>T;T;T--)
{
for(cin>>n,i=1;i<=n;i++)
cin>>s[i]>>e[i]>>d[i];
if(!(sum(2147483647)&1))cout<<"There's no weakness.\n";
else
{
for(l=0,r=2147483647;l<r;)//二分查找
{
mid=(long long)(l+r)>>1;
if(sum(mid)&1) r=mid;
else l=mid+1;
}
cout<<l<<' '<<sum(l)-sum(l-1)<<endl;
}
}
return 0;
}