【YBT高效进阶】1基础算法/3二分算法/2防具布置

【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;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/115099494