[NOIp2012] luogu P1083 借教室
该*的英语,这么长还要背。
题目描述
你有 个数 , 次操作,每次操作将 区间的每个数减去 。要求任何时刻 都有 ,请你告诉我最多可以合法地执行多少次操作。
Solution
很明显这是个差分数组对吧。
二分答案即可,每次线性地判断该状态是否合法。时间复杂度 。
#include<cstdio>
#include<cstdlib>
#include<cstring>
const int MAXN=1000010;
int n,m;
int d[MAXN],D[MAXN];
int sx[MAXN],sy[MAXN],sd[MAXN];
int check(int x){
for(int i=1;i<=n;++i)
d[i]=D[i];
for(int i=1;i<=x;++i){
d[sx[i]]-=sd[i];
d[sy[i]+1]+=sd[i];
}
// printf("%d\t",x);
// for(int i=1;i<=n;++i)
// printf("%d ",d[i]);
// puts("");
int tmp=0;
for(int i=1;i<=n;++i){
tmp+=d[i];
if(tmp<0) return 0;
}
return 1;
}
inline int read(){
int x=0; char c;
do c=getchar(); while(c<'0'||c>'9');
while(c>='0'&&c<='9')
x=x*10+c-48,c=getchar();
return x;
}
int main(){
n=read();m=read();d[0]=0;
for(int i=1;i<=n;++i){
d[i]=read();
D[i]=d[i]-d[i-1];
}
for(int i=1;i<=m;++i){
sd[i]=read();
sx[i]=read();
sy[i]=read();
}
int l=0,r=n,mid,ans=-1;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
puts(ans==n?"0":"-1");
if(ans!=n) printf("%d",ans+1);
}

浙公网安备 33010602011771号