这题其实就是一道Splay的区间修改模板题,太棒啦,又水了一篇blog!
其实Splay的区间加上一个值用的就是线段树的延迟标记的思想,实现就和下放区间反转的标记一样。区间求最大值也是类似的。
于是这题就是练一下码力的水题。
附上AC代码:
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=5e4+10;
int n,m,mx[N],rt,f[N],sz[N],ch[N][2],w[N],o,x,y,v,tag[N],rev[N];
inline char nc(void){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc());
return (void)(a*=f);
}
inline void updata(int k){return (void)(mx[k]=max(max(mx[ch[k][0]],mx[ch[k][1]]),w[k]),sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1);}
inline void rotate(int x){
int y=f[x],op=(ch[y][1]==x);
ch[y][op]=ch[x][op^1];
if (ch[x][op^1]) f[ch[x][op^1]]=y;
f[x]=f[y];
if (f[y]) ch[f[y]][ch[f[y]][1]==y]=x;
f[y]=x,ch[x][op^1]=y;
return updata(y),updata(x);
}
inline void splay(int x,int ed){
for (int fa=f[x]; fa!=ed; rotate(x),fa=f[x])
if (f[fa]!=ed) rotate((ch[fa][0]==x)==(ch[f[fa]][0]==fa)?fa:x);
if (!ed) rt=x;
return;
}
inline void build(int l,int r,int pre){
if (l>r) return;
if (l==r) return (void)(f[l]=pre,sz[l]=1,ch[pre][l>pre]=l);
int mid=l+r>>1;
build(l,mid-1,mid),build(mid+1,r,mid);
return (void)(f[mid]=pre,updata(mid),ch[pre][mid>pre]=mid);
}
inline void push(int k){
if (tag[k]){
if (ch[k][0]) tag[ch[k][0]]+=tag[k],mx[ch[k][0]]+=tag[k],w[ch[k][0]]+=tag[k];
if (ch[k][1]) tag[ch[k][1]]+=tag[k],mx[ch[k][1]]+=tag[k],w[ch[k][1]]+=tag[k];
tag[k]=0;
}
if (rev[k]) rev[ch[k][0]]^=1,rev[ch[k][1]]^=1,rev[k]=0,swap(ch[k][0],ch[k][1]);
}
inline int find(int k,int rk){
if (tag[k]||rev[k]) push(k);
if (sz[ch[k][0]]>=rk) return find(ch[k][0],rk);
if (sz[ch[k][0]]+1==rk) return k;
return find(ch[k][1],rk-sz[ch[k][0]]-1);
}
inline void add(int x,int y,int v){
int l=find(rt,x),r=find(rt,y+2);
splay(l,0),splay(r,rt);
int k=ch[r][0];
return (void)(tag[k]+=v,mx[k]+=v,w[k]+=v);
}
inline void flip(int x,int y){
int l=find(rt,x),r=find(rt,y+2);
return (void)(splay(l,0),splay(r,rt),rev[ch[r][0]]^=1);
}
inline void query(int x,int y){
int l=find(rt,x),r=find(rt,y+2);
splay(l,0),splay(r,rt);
printf("%d\n",mx[ch[r][0]]);
}
int main(void){
read(n),read(m),mx[0]=-2e9,build(1,n+2,0),rt=(n+3)>>1;
while (m--){
read(o),read(x),read(y);
switch (o){
case 1: read(v),add(x,y,v);break;
case 2: flip(x,y);break;
case 3: query(x,y);break;
}
}
return 0;
}