题解:P8856 [POI2002] 火车线路
题意简述
对长度为
思路
我们知道因为数组修改前的最大值肯定不会大于
又有区间查询,又有区间修改,想到什么?没错,就是分块!当然有一个细节就是区间修改的右边界要减一,因为此时已经下车了。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=60005,T=255;
int n,s,m;//n个点,s为座位数量,m为操作次数。
int block,t,st[T],ed[T],pos[N];
int a[N],add[T],mx[T];//a存数组,add存每个块的标记,mx为块的最大值。
void build(){//初始化。
block=sqrt(n);
t=n/block;
if(n%block)t++;
for(int i=1;i<=t;i++){
st[i]=(i-1)*block+1;
ed[i]=i*block;
}
ed[t]=n;
for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
}
int update(int l,int r,int d){//更新函数,由于增加一次判断一次所以把判断加入。
int p=pos[l],q=pos[r];
if(p==q){//如果在一个块,暴力做。
int tmblar=0;//The max between l and r.
for(register int i=l;i<=r;i++)tmblar=max(tmblar,a[i]+add[p]);
//先求出原有的最大值。
if(tmblar+d>s)return 0;//判断,若不行直接返回0。
mx[p]=0;//暴力重新算最大值。
for(register int i=st[p];i<=ed[p];i++){
if(l<=i&&i<=r)a[i]+=d;//增加。
mx[p]=max(mx[p],a[i]+add[p]);
}
return 1;//可以被满足。
}
else{
int tmblar=0;//The max between l and r.
for(register int i=l;i<=ed[p];i++)tmblar=max(tmblar,a[i]+add[p]);
for(register int i=p+1;i<=q-1;i++)tmblar=max(tmblar,mx[i]);
for(register int i=st[q];i<=r;i++)tmblar=max(tmblar,a[i]+add[q]);
//求出原有的最大值。
if(tmblar+d>s)return 0;//判断,若不行直接返回0。
mx[p]=0;//暴力重新算最大值。
for(register int i=st[p];i<=ed[p];i++){
if(l<=i)a[i]+=d;
mx[p]=max(mx[p],a[i]+add[p]);
}
for(register int i=p+1;i<=q-1;i++){
add[i]+=d;//对整个块标记。
mx[i]+=d;//因为都加了d,所以最大值也加d。
}
mx[q]=0;
for(register int i=st[q];i<=ed[q];i++){
if(i<=r)a[i]+=d;
mx[q]=max(mx[q],a[i]+add[q]);
}
return 1;//可以被满足。
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>s>>m;
build();
for(register int i=1;i<=m;i++){
int L,R,D;
cin>>L>>R>>D;
if(update(L,R-1,D))cout<<"T"<<'\n';//一定是R-1!!!
else cout<<"N"<<'\n';//用\n可以快一点。
}
return 0;
}
吸氧可过,不开就超时一点点。