题解:P10460 防线
P10460 防线
题目链接
二分 and 一点数学知识
这道题题目看着很长,但只要把握重点内容,就可以轻松解决。
题目中正向枚举很明显会 TLE,所以我们想到二分答案。再观察题目发现,只有一个地方有奇数个防具,所以我们只需判断
代码如下
#include <bits/stdc++.h>
using namespace std;
int a[1000001],b[1000001],c[1000001],n;
int pd(int x)//判断x之前的防具个数
{
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]<=x)
ans+=(min(x,b[i])-a[i])/c[i]+1;//利用等差数列公式求防具和
}
return ans;
}
long long read()
{
char ch=getchar();
int x=0,f=1;
while(!isdigit(ch)){
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-'0',ch=getchar();
}
return x*f;
}//快读模版
void write(long long x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}//快写模版
int main()
{
int T;
T=read();
for(int i=1;i<=T;i++){
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
b[i]=read();
c[i]=read();
}
if(pd(2147483647)%2==0)
{
printf("There's no weakness.\n");
continue;
}//如果所有防具和为偶数,则说明没有破绽
int l=0,r=2147483647;//题目数据int范围
while(l<r)
{
int mid=(l+r)>>1;
if(pd(mid)&1)
r=mid;
else
l=mid+1;
}//二分模版
write(l);
printf(" ");
write(pd(l)-pd(l-1));//位置l上的防具数量,用前缀和实现
printf("\n");
}
}
码风不佳,请勿见怪。
欢迎 dalao 们提出改进建议。