支持某位置單點插入,區間加法,區間最小值,單點刪除,區間翻轉,區間輪轉。
甚至還可以再加上區間賦蓋,區間和,區間最大子段和等一系列線段樹可進行的操作。
splay打包帶走
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
const int inf=1e9;
int tot,rt;
void init(){tot=rt=0;}
int siz[maxn],val[maxn],rev[maxn],add[maxn],minn[maxn],ch[maxn][2],f[maxn],W[maxn];
bool which(int x){ return ch[f[x]][1]==x; }
void connect(int s,int fa,int lr){
ch[fa][lr]=s;
f[s]=fa;
}
void pushup(int k){
if(k){
minn[k]=val[k];
siz[k]=1;
if(ch[k][0]) siz[k]+=siz[ch[k][0]],minn[k]=min(minn[k],minn[ch[k][0]]);
if(ch[k][1]) siz[k]+=siz[ch[k][1]],minn[k]=min(minn[k],minn[ch[k][1]]);
}
}
void pushdown(int k){
if(!k) return ;
if(rev[k]){
if(ch[k][0]) rev[ch[k][0]]^=1;
if(ch[k][1]) rev[ch[k][1]]^=1;
swap(ch[k][0],ch[k][1]);
rev[k]=0;
}
if(add[k]){
if(ch[k][0]) val[ch[k][0]]+=add[k],minn[ch[k][0]]+=add[k],add[ch[k][0]]+=add[k];
if(ch[k][1]) val[ch[k][1]]+=add[k],minn[ch[k][1]]+=add[k],add[ch[k][1]]+=add[k];
add[k]=0;
}
}
queue<int> q;
int newnode(int w){
int k;
if(q.size()) { k=q.front(); q.pop(); }
else k=++tot;
rev[k]=add[k]=f[k]=ch[k][0]=ch[k][1]=0;
minn[k]=val[k]=w;
siz[k]=1;
return k;
}
void clear(int k){
rev[k]=add[k]=f[k]=ch[k][0]=ch[k][1]=minn[k]=val[k]=0;
q.push(k);
}
int build(int l,int r,int fa){
if(l>r) return 0;
int mid=l+r>>1;
int now=newnode(W[mid]);
f[now]=fa;
ch[now][0]=build(l,mid-1,now);
ch[now][1]=build(mid+1,r,now);
pushup(now);
return now;
}
void rotate(int x){
pushdown(f[x]),pushdown(x);
int old=f[x],oldf=f[old],who=which(x);
connect(ch[x][who^1],old,who);
if(oldf) connect(x,oldf,which(old));
f[x]=oldf;
connect(old,x,who^1);
pushup(old),pushup(x);
}
//將x轉到pos的兒子處;
void splay(int x,int pos){
for(int fa;(fa=f[x])!=pos;rotate(x))
if(f[fa]!=pos) rotate(which(fa)==which(x)?fa:x);
if(!pos) rt=x;
}
int kth(int x){
int now=rt;
while(1){
pushdown(now);
if(ch[now][0]&&x<=siz[ch[now][0]]) now=ch[now][0];
else{
x-=siz[ch[now][0]];
if(x==1) return now;
--x;
now=ch[now][1];
}
}
return -1;
}
pair<int,int> splayLR(int l,int r){
int L=kth(l);
int R=kth(r);
splay(L,0);
splay(R,L);
return make_pair(L,R);
}
void add_to_some(int l,int r,int x){
if(l>r) swap(l,r);
pair<int,int> P=splayLR(l-1,r+1);
int L=P.first,R=P.second;
add[ch[R][0]]+=x;
minn[ch[R][0]]+=x;
val[ch[R][0]]+=x;
pushup(R),pushup(rt);
}
void reverse(int l,int r){
if(l>r) swap(l,r);
pair<int,int> P=splayLR(l-1,r+1);
int L=P.first,R=P.second;
rev[ch[R][0]]^=1;
}
void insert(int pos,int x){
pair<int,int> P=splayLR(pos,pos+1);
int L=P.first,R=P.second;
int now=newnode(x);
connect(now,R,0);
pushdown(R),pushup(rt);
}
void del(int pos){
pair<int,int> P=splayLR(pos-1,pos+1);
int L=P.first,R=P.second;
clear(ch[R][0]);
ch[R][0]=0;
pushup(R),pushup(rt);
}
int askMin(int l,int r){
if(l>r) swap(l,r);
pair<int,int> P=splayLR(l-1,r+1);
return minn[ch[P.second][0]];
}
void init(int n){
init();
W[1]=-inf;
W[n+2]=inf;
for(int i=2;i<=n+1;++i) scanf("%d",&W[i]);
rt=build(1,n+2,0);
}
void exchange(int l,int r,int x){
if(l>r) swap(l,r);
x%=(r-l+1);
if(!x) return ;
int l1=l,r1=r-x,l2=r-x+1,r2=r;
pair<int,int> pos2=splayLR(l2-1,r2+1);
int L=pos2.first,R=pos2.second;
int temp_r=ch[R][0]; ch[R][0]=0;
pushup(R),pushup(rt);
pair<int,int> pos1=splayLR(l1-1,l1);
R=pos1.second;
ch[R][0]=temp_r;
f[temp_r]=R;
pushup(R),pushup(rt);
}
char s[9];
/*
A 區間加法
D 刪除下標爲x的數
M 區間最小值
E 區間翻轉
else 區間輪換x次;
*/
int main(){
int n,q,l,r,x;
scanf("%d",&n);
init(n);
scanf("%d",&q);
while(q--){
scanf("%s",s);
if(s[0]=='A'){ scanf("%d%d%d",&l,&r,&x); add_to_some(++l,++r,x); }
else if(s[0]=='I'){ scanf("%d%d",&l,&x); insert(++l,x); }
else if(s[0]=='D'){ scanf("%d",&x); del(++x); }
else if(s[0]=='M'){ scanf("%d%d",&l,&r); printf("%d\n",askMin(++l,++r)); }
else if(s[3]=='E'){ scanf("%d%d",&l,&r); reverse(++l,++r); }
else{ scanf("%d%d%d",&l,&r,&x); exchange(++l,++r,x); }
}
return 0;
}