Solution Set - Splay
A[洛谷P3369]维护集合,支持插入,删除,查询\(x\)的排名,查询排名\(x\)的数,查询前驱,查询后继。
B[洛谷P3391]维护一个序列,支持区间翻转。
C[洛谷P3380]维护数列,支持单点修改,在某区间内查询\(x\)的排名,排名为\(x\)的数,前驱,后继。
D[洛谷P4036]维护一个字符串,支持单点修改,单点插入,询问两端后缀的最长公共前缀。
E[洛谷P4309]依次将\(1,2,...,n\)插入一个数列中,询问每次插入后的LIS。
F[洛谷P2042]维护一个数列,支持单点插入,区间删除,区间覆盖,区间翻转,查询区间和,查询最大子串和。
G[POJ3580]维护一个数列,支持区间加,区间翻转,区间轮换,单点插入,单点删除,查询区间最小值。
H[洛谷P3215]维护一个括号序列,支持区间覆盖,区间翻转,区间取反,查询将某个区间变为合法至少需要修改的括号数。
I[洛谷P3224]维护一张图,支持连边,查询与某个点连通的点中的第\(k\)小点权。
Splay:伸展树,是一种二叉搜索树,基本操作为旋转和伸展(即将某个点旋转到根)。均摊\(O(n\log n)\)。
Splay相当灵活,常用的处理手段是把点\(l-1\)转到根,再把\(r+1\)转到\(l-1\)的右儿子,此时\(r+1\)的左儿子代表区间\([l,r]\)。
在此基础上,可以像线段树一样用儿子更新信息,打懒惰标记。
A平衡树模板。
B使用懒标记的模板。注意在维护下标的平衡树,在平衡树的中序遍历中位于第\(k\)位的点就代表数列中第\(k\)个数。
C线段树套平衡树,在线段树的每个点开平衡树记录该区间的所有数。
D平衡树维护字符串哈希值,只需要修改push_up即可。询问时二分。
E注意到每次插入不影响已插入的点的DP值,故直接维护即可。
F,G都是懒标记,注意每次提取区间,打标记之后都要push_up。求最大子串和可以维护前缀最大和后缀最大。
H记录把()看做匹配,左边留下的)数和右边留下的(数,以及取反之后的结果,Splay维护即可。
I平衡树的启发式合并。
点击查看A题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,INF=1e9;
int n;
struct Splay{
int rt,tot,fa[N],ch[N][2],val[N],cnt[N],siz[N];
void push_up(int p){siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+cnt[p];}
bool get(int p){return p==ch[fa[p]][1];}
void clear(int p){fa[p]=ch[p][0]=ch[p][1]=val[p]=cnt[p]=siz[p]=0;}
void rotate(int x){
int y=fa[x],z=fa[y],op=1-get(x);
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
void ins(int v){
if(!tot){rt=tot=1;val[1]=v;cnt[1]=siz[1]=1;return;}
int p=rt,f=0;
while(1){
if(val[p]==v){++cnt[p];++siz[p];push_up(f);splay(p);break;}
f=p;p=ch[p][val[p]<v];
if(!p){
val[p=++tot]=v;cnt[p]=siz[p]=1;
fa[tot]=f;ch[f][val[f]<v]=p;
push_up(f);splay(p);break;
}
}
}
bool find(int v){
int p=rt;
while(p){
if(val[p]==v){splay(p);return true;}
p=ch[p][val[p]<v];
}return false;
}
void merge(int x,int y){
while(ch[x][1])x=ch[x][1];
splay(x);ch[x][1]=y;fa[y]=x;push_up(x);
}
void del(int v){
if(!find(v))return;
if(cnt[rt]>1){--cnt[rt],--siz[rt];return;}
int x=ch[rt][0],y=ch[rt][1];
fa[x]=fa[y]=0;clear(rt);
if(!x||!y){rt=x+y;return;}
merge(x,y);
}
int rank(int v){
find(v);
return siz[ch[rt][0]]+1;
}
int kth(int k){
int p=rt;
while(1){
if(ch[p][0]&&k<=siz[ch[p][0]])p=ch[p][0];
else{
k-=cnt[p]+siz[ch[p][0]];
if(k<=0){splay(p);return val[p];}
p=ch[p][1];
}
}
}
int nxt(int x,int op){
ins(x);int p=ch[rt][op^1];
if(!p)return -1;
while(ch[p][op])p=ch[p][op];
int res=val[p];del(x);
return res;
}
}cst;
int main(){
scanf("%d",&n);
cst.ins(INF);cst.ins(-INF);
for(int i=1,op,x;i<=n;i++){
scanf("%d%d",&op,&x);
if(op==1)cst.ins(x);
if(op==2)cst.del(x);
if(op==3)printf("%d\n",cst.rank(x)-1);
if(op==4)printf("%d\n",cst.kth(x+1));
if(op==5)printf("%d\n",cst.nxt(x,1));
if(op==6)printf("%d\n",cst.nxt(x,0));
}
return 0;
}
点击查看B题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,ans[N],cnt;
struct Splay{
int rt,tot,fa[N],ch[N][2],val[N],tag[N],siz[N];
void push_up(int p){siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;}
int build(int l,int r){
if(l==r){push_up(l);return l;}
int p=l+r>>1;
if(l<p)fa[ch[p][0]=build(l,p-1)]=p;
if(p<r)fa[ch[p][1]=build(p+1,r)]=p;
push_up(p);
return p;
}
bool get(int p){return p==ch[fa[p]][1];}
void push_down(int p){
if(!tag[p])return;
tag[ch[p][0]]^=1;tag[ch[p][1]]^=1;
tag[p]=0;swap(ch[p][0],ch[p][1]);
}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
int kth(int k){
int p=rt;
while(1){
push_down(p);
if(ch[p][0]&&k<=siz[ch[p][0]])p=ch[p][0];
else{
k-=siz[ch[p][0]]+1;
if(k<=0)return p;
p=ch[p][1];
}
}
}
void update(int l,int r){
l=kth(l-1);splay(l,0);
r=kth(r+1);splay(r,l);
tag[ch[r][0]]^=1;
}
void dfs(int p){
push_down(p);
if(ch[p][0])dfs(ch[p][0]);
if(p!=1&&p!=n+2)printf("%d ",p-1);
if(ch[p][1])dfs(ch[p][1]);
}
}cst;
int main(){
scanf("%d%d",&n,&m);
cst.rt=cst.build(1,n+2);
for(int i=1,l,r;i<=m;i++){
scanf("%d%d",&l,&r);
cst.update(l+1,r+1);
}
cst.dfs(cst.rt);
return 0;
}
点击查看C题代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5,M=2.22e7+5,INF=2147483647;
int n,m,a[N];
struct Splay{
int rt[N*10],tot,fa[M],ch[M][2],val[M],cnt[M],siz[M];
void push_up(int p){siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+cnt[p];}
bool get(int p){return p==ch[fa[p]][1];}
void clear(int p){fa[p]=ch[p][0]=ch[p][1]=val[p]=cnt[p]=siz[p]=0;}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int id,int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt[id]=x;
}
void ins(int id,int v){
if(!rt[id]){rt[id]=++tot;val[tot]=v;cnt[tot]=siz[tot]=1;return;}
int p=rt[id],f=0;
while(1){
if(val[p]==v){++cnt[p];++siz[p];push_up(f);splay(id,p);break;}
f=p;p=ch[p][val[p]<v];
if(!p){
val[p=++tot]=v;cnt[p]=siz[p]=1;
fa[p]=f;ch[f][val[f]<v]=p;
push_up(f);splay(id,p);break;
}
}
}
bool find(int id,int v){
int p=rt[id];
while(1){
if(val[p]==v){splay(id,p);return true;}
p=ch[p][val[p]<v];
}return false;
}
void merge(int id,int x,int y){
while(ch[x][1])x=ch[x][1];
splay(id,x);ch[x][1]=y;fa[y]=x;push_up(x);
}
void del(int id,int v){
if(!find(id,v))return;
if(cnt[rt[id]]>1){--cnt[rt[id]];--siz[rt[id]];return;}
int x=ch[rt[id]][0],y=ch[rt[id]][1];
fa[x]=fa[y]=0;clear(rt[id]);
if(!x||!y)rt[id]=x+y;else merge(id,x,y);
}
int rank(int id,int v){
int p=rt[id],res=0;
while(p){
if(v<val[p])p=ch[p][0];
else{
res+=siz[ch[p][0]];
if(v==val[p]){splay(id,p);return res;}
res+=cnt[p];p=ch[p][1];
}
}
return res;
}
int nxt(int id,int v,int op){
ins(id,v);int p=ch[rt[id]][op^1];
if(!p){del(id,v);return op?-INF:INF;}
while(ch[p][op])p=ch[p][op];
int res=val[p];splay(id,p);del(id,v);
return res;
}
}cst;
struct SegmentTree{
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
void modify(int p,int l,int r,int x,int v,int op){
if(!op)cst.del(p,v);else cst.ins(p,v);
if(l==r)return;
if(x<=mid)modify(ls,l,mid,x,v,op);
else modify(rs,mid+1,r,x,v,op);
}
int query_rank(int p,int l,int r,int L,int R,int v){
if(l>=L&&r<=R)return cst.rank(p,v);
if(R<=mid)return query_rank(ls,l,mid,L,R,v);
if(L>mid)return query_rank(rs,mid+1,r,L,R,v);
return query_rank(ls,l,mid,L,R,v)+query_rank(rs,mid+1,r,L,R,v);
}
int query_kth(int L,int R,int k){
int l=0,r=1e8,res=0;
while(l<=r){
int MID=mid;
if(query_rank(1,1,n,L,R,MID)>k)r=MID-1;
else l=MID+1,res=MID;
}
return res;
}
int query_nxt(int p,int l,int r,int L,int R,int v,int op){
if(l>=L&&r<=R)return cst.nxt(p,v,op);
if(R<=mid)return query_nxt(ls,l,mid,L,R,v,op);
if(L>mid)return query_nxt(rs,mid+1,r,L,R,v,op);
return op?max(query_nxt(ls,l,mid,L,R,v,op),query_nxt(rs,mid+1,r,L,R,v,op)):
min(query_nxt(ls,l,mid,L,R,v,op),query_nxt(rs,mid+1,r,L,R,v,op));
}
}seg;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",a+i),seg.modify(1,1,n,i,a[i],1);
for(int i=1,op,l,r,x;i<=m;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",seg.query_rank(1,1,n,l,r,x)+1);
}
if(op==2){
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",seg.query_kth(l,r,x-1));
}
if(op==3){
scanf("%d%d",&l,&x);
seg.modify(1,1,n,l,a[l],0);a[l]=x;
seg.modify(1,1,n,l,a[l],1);
}
if(op==4){
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",seg.query_nxt(1,1,n,l,r,x,1));
}
if(op==5){
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",seg.query_nxt(1,1,n,l,r,x,0));
}
}
return 0;
}
点击查看D题代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=1e5+5;
int n,m,x,y;char s[N],op[3],ch[3];ull r[N],base=131;
struct Splay{
int rt,tot,fa[N],ch[N][2],siz[N];ull val[N],h[N];
void push_up(int p){
h[p]=h[ch[p][0]]+val[p]*r[siz[ch[p][0]]]+h[ch[p][1]]*r[siz[ch[p][0]]+1];
siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;
}
bool get(int p){return p==ch[fa[p]][1];}
void clear(int p){fa[p]=ch[p][0]=ch[p][1]=siz[p]=val[p]=h[p]=0;}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
int build(int l,int r){
int mid=l+r>>1;val[mid]=s[mid];
if(l<mid)fa[ch[mid][0]=build(l,mid-1)]=mid;
if(r>mid)fa[ch[mid][1]=build(mid+1,r)]=mid;
push_up(mid);return mid;
}
int find(int x){
int p=rt;
while(1){
if(siz[ch[p][0]]>=x)p=ch[p][0];
else if(siz[ch[p][0]]==x-1)return p;
else x-=siz[ch[p][0]]+1,p=ch[p][1];
}
}
ull query(int l,int r){
l=find(l-1);splay(l);r=find(r+1);splay(r,l);
return h[ch[r][0]];
}
void modify(int x,char c){splay(find(x));val[rt]=c;push_up(rt);}
void ins(int x,char c){
int l=find(x);splay(l);int r=find(x+1);splay(r,l);
ch[ch[rt][1]][0]=++tot;fa[tot]=ch[rt][1];val[tot]=h[tot]=c;
splay(tot);
}
}cst;
int main(){
r[0]=1;for(int i=1;i<N;i++)r[i]=r[i-1]*base;
scanf("%s",s+2);n=strlen(s+2);
cst.rt=cst.build(1,n+2);cst.tot=n+2;
scanf("%d",&m);
while(m--){
scanf("%s",op);
if(op[0]=='Q'){
scanf("%d%d",&x,&y);
int l=1,r=min(n-x+1,n-y+1),res=0;
while(l<=r){
int mid=l+r>>1;
if(cst.query(x+1,x+mid)==cst.query(y+1,y+mid))
res=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",res);
}
if(op[0]=='R'){scanf("%d",&x);scanf("%s",ch);cst.modify(x+1,ch[0]);}
if(op[0]=='I'){scanf("%d",&x);scanf("%s",ch);++n;cst.ins(x+1,ch[0]);}
}
return 0;
}
点击查看E题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,ans;
struct Splay{
int rt,tot,fa[N],ch[N][2],siz[N],mx[N],dp[N];
void init(){rt=1;tot=2;ch[1][1]=2;fa[2]=1;siz[1]=2;siz[2]=1;}
void push_up(int p){
mx[p]=max(max(mx[ch[p][0]],mx[ch[p][1]]),dp[p]);
siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;
}
bool get(int p){return p==ch[fa[p]][1];}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
int kth(int k){
int p=rt;
while(1){
if(ch[p][0]&&k<=siz[ch[p][0]])p=ch[p][0];
else{
k-=siz[ch[p][0]]+1;
if(k<=0)return p;
p=ch[p][1];
}
}
}
void update(int x){
int l=kth(x+1);splay(l);
int r=kth(x+2);splay(r,l);
ch[r][0]=++tot;fa[tot]=r;siz[tot]=1;splay(tot);
dp[rt]=mx[ch[rt][0]]+1;
printf("%d\n",ans=max(ans,dp[rt]));
}
}cst;
int main(){
scanf("%d",&n);cst.init();
for(int i=1,x;i<=n;i++){scanf("%d",&x);cst.update(x);}
return 0;
}
//
点击查看F题代码
#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
const int N=3e6+5,INF=1e9;
int n,m,a[N];char opt[15];
struct Splay{
int rt,tot,fa[N],ch[N][2],siz[N];
int tag[N],tag2[N],val[N],sum[N],lmx[N],rmx[N],mx[N]={-INF};
void clear(int p){
fa[p]=ch[p][0]=ch[p][1]=siz[p]=val[p]=0;
tag[p]=sum[p]=0;tag2[p]=lmx[p]=rmx[p]=mx[p]=-INF;
}
void push_up(int p){
siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;
if(siz[p]==1){sum[p]=lmx[p]=rmx[p]=mx[p]=val[p];return;}
sum[p]=sum[ch[p][0]]+sum[ch[p][1]]+val[p];
lmx[p]=max(lmx[ch[p][0]],sum[ch[p][0]]+val[p]+max(0,lmx[ch[p][1]]));
rmx[p]=max(rmx[ch[p][1]],sum[ch[p][1]]+val[p]+max(0,rmx[ch[p][0]]));
mx[p]=max(max(mx[ch[p][0]],mx[ch[p][1]]),
max(rmx[ch[p][0]],0)+val[p]+max(lmx[ch[p][1]],0));
}
void push_down(int p){
int lc=ch[p][0],rc=ch[p][1];
if(tag2[p]!=-INF){
int v=tag2[p];tag2[p]=-INF;
if(lc)tag2[lc]=val[lc]=v,sum[lc]=siz[lc]*v,
lmx[lc]=rmx[lc]=mx[lc]=v<=0?v:siz[lc]*v;
if(rc)tag2[rc]=val[rc]=v,sum[rc]=siz[rc]*v,
lmx[rc]=rmx[rc]=mx[rc]=v<=0?v:siz[rc]*v;
}
if(tag[p]){
if(lc)tag[lc]^=1,swap(ch[lc][0],ch[lc][1]),swap(lmx[lc],rmx[lc]);
if(rc)tag[rc]^=1,swap(ch[rc][0],ch[rc][1]),swap(lmx[rc],rmx[rc]);
tag[p]=0;
}
}
int build(int l,int r){
if(l==r){val[l]=a[l];tag2[l]=-INF;push_up(l);return l;}
int p=l+r>>1;val[p]=a[p];tag2[p]=-INF;
if(l<p)fa[ch[p][0]=build(l,p-1)]=p;
if(p<r)fa[ch[p][1]=build(p+1,r)]=p;
push_up(p);return p;
}
bool get(int p){return p==ch[fa[p]][1];}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
int kth(int k){
int p=rt;
while(1){
push_down(p);
if(ch[p][0]&&k<=siz[ch[p][0]])p=ch[p][0];
else{k-=siz[ch[p][0]]+1;if(k<=0)return p;p=ch[p][1];}
}
}
void ins(int p,int v){
int x=kth(p),y=kth(p+1);
splay(x);splay(y,x);
ch[y][0]=++tot;fa[tot]=y;tag2[tot]=-INF;
val[tot]=v;push_up(tot);splay(tot);
}
void range(int&l,int&r){
l=kth(l);r=kth(r+2);
splay(l);splay(r,l);
push_up(r);push_up(l);
}
void del(int l,int r){range(l,r);clear(ch[r][0]);ch[r][0]=0;}
void update1(int l,int r){
range(l,r);int p=ch[r][0];tag[p]^=1;
swap(ch[p][0],ch[p][1]);swap(lmx[p],rmx[p]);
}
void update2(int l,int r,int v){
range(l,r);int p=ch[r][0];
tag2[p]=val[p]=v;sum[p]=siz[p]*v;
lmx[p]=rmx[p]=mx[p]=v<=0?v:siz[p]*v;
}
int query(int l,int r){range(l,r);return sum[ch[r][0]];}
int maxsum(int l,int r){range(l,r);return mx[ch[r][0]];}
}cst;
int main(){
n=read();m=read();
for(int i=2;i<=n+1;i++)a[i]=read();
cst.rt=cst.build(1,n+2);cst.tot=n+2;
while(m--){
scanf("%s",opt);
if(opt[2]=='S'){
int p=read()+1,k=read();n+=k;
while(k--)cst.ins(p,read()),++p;
}
if(opt[2]=='L'){
int p=read(),k=read();n-=k;
if(k)cst.del(p,p+k-1);
}
if(opt[2]=='K'){
int p=read(),k=read(),c=read();
if(k)cst.update2(p,p+k-1,c);
}
if(opt[2]=='V'){
int p=read(),k=read();
if(k)cst.update1(p,p+k-1);
}
if(opt[2]=='T'){
int p=read(),k=read();
if(k)printf("%d\n",cst.query(p,p+k-1));else printf("0\n");
}
if(opt[2]=='X')printf("%d\n",cst.maxsum(1,n));
}
return 0;
}
点击查看G题代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
const int N=2e5+5,INF=1e9;
int n,m,a[N];char opt[15];
struct Splay{
int rt,tot,fa[N],ch[N][2],siz[N];
int tag[N],tag2[N],val[N],mn[N];
void clear(int p){
fa[p]=ch[p][0]=ch[p][1]=siz[p]=val[p]=0;
tag[p]=tag2[p]=0;mn[p]=INF;
}
void push_up(int p){
siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;
mn[p]=min(min(mn[ch[p][0]],mn[ch[p][1]]),val[p]);
}
void push_down(int p){
int lc=ch[p][0],rc=ch[p][1];
if(tag2[p]){
int v=tag2[p];tag2[p]=0;
if(lc)val[lc]+=v,mn[lc]+=v,tag2[lc]+=v;
if(rc)val[rc]+=v,mn[rc]+=v,tag2[rc]+=v;
}
if(tag[p]){
if(lc)tag[lc]^=1,swap(ch[lc][0],ch[lc][1]);
if(rc)tag[rc]^=1,swap(ch[rc][0],ch[rc][1]);
tag[p]=0;
}
}
int build(int l,int r){
if(l==r){val[l]=a[l];push_up(l);return l;}
int p=l+r>>1;val[p]=a[p];
if(l<p)fa[ch[p][0]=build(l,p-1)]=p;
if(p<r)fa[ch[p][1]=build(p+1,r)]=p;
push_up(p);return p;
}
bool get(int p){return p==ch[fa[p]][1];}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
int kth(int k){
int p=rt;
while(1){
push_down(p);
if(ch[p][0]&&k<=siz[ch[p][0]])p=ch[p][0];
else{k-=siz[ch[p][0]]+1;if(k<=0)return p;p=ch[p][1];}
}
}
void ins(int p,int v){
int x=kth(p),y=kth(p+1);
splay(x);splay(y,x);
ch[y][0]=++tot;fa[tot]=y;
val[tot]=v;push_up(tot);splay(tot);
}
void range(int&l,int&r){
l=kth(l);r=kth(r+2);
splay(l);splay(r,l);
push_up(r);push_up(l);
}
void del(int l,int r){range(l,r);clear(ch[r][0]);ch[r][0]=0;}
void move(int l,int r,int t){
int len=r-l+1;t=(t%len+len)%len;if(!t)return;
int x=l,y=r-t;range(x,y);int p=ch[y][0];ch[y][0]=fa[p]=0;push_up(y);
x=l+t;y=l+t-1;range(x,y);ch[y][0]=p;fa[p]=y;push_up(y);
}
void update1(int l,int r){
range(l,r);int p=ch[r][0];tag[p]^=1;
swap(ch[p][0],ch[p][1]);
}
void update2(int l,int r,int v){
range(l,r);int p=ch[r][0];
tag2[p]+=v;val[p]+=v;mn[p]+=v;
}
int query(int l,int r){range(l,r);return mn[ch[r][0]];}
void print(int p){
push_down(p);
if(ch[p][0])print(ch[p][0]);
printf("%d ",val[p]);
if(ch[p][1])print(ch[p][1]);
}
}cst;
int main(){
n=read();cst.mn[0]=INF;
for(int i=2;i<=n+1;i++)a[i]=read();
cst.rt=cst.build(1,n+2);cst.tot=n+2;
m=read();
while(m--){
scanf("%s",opt);
if(opt[0]=='A'){int l=read(),r=read(),c=read();cst.update2(l,r,c);}
if(opt[0]=='R'&&opt[3]=='E'){int l=read(),r=read();cst.update1(l,r);}
if(opt[0]=='R'&&opt[3]=='O'){int l=read(),r=read(),t=read();cst.move(l,r,t);}
if(opt[0]=='I'){int p=read(),v=read();cst.ins(p+1,v);}
if(opt[0]=='D'){int p=read();cst.del(p,p);}
if(opt[0]=='M'){int l=read(),r=read();printf("%d\n",cst.query(l,r));}
}
return 0;
}
点击查看H题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m;char s[N],opt[10],ch[3];
struct Splay{
int rt,fa[N],ch[N][2],siz[N],val[N];
int lef[N][2],rig[N][2],tag1[N],tag2[N],tag3[N];
void push_up(int p){
int lc=ch[p][0],rc=ch[p][1],l1,r1,l2,r2;
siz[p]=siz[lc]+siz[rc]+1;
l1=lef[lc][0];r1=rig[lc][0];l2=lef[rc][0];r2=rig[rc][0];
if(val[p]==-1)++r1;if(val[p]==1)++l2;
lef[p][0]=l1+l2-min(r1,l2);rig[p][0]=r1+r2-min(r1,l2);
l1=lef[lc][1];r1=rig[lc][1];l2=lef[rc][1];r2=rig[rc][1];
if(val[p]==-1)++l2;if(val[p]==1)++r1;
lef[p][1]=l1+l2-min(r1,l2);rig[p][1]=r1+r2-min(r1,l2);
}
void tag(int p,int op){
if(op==2){
tag2[p]^=1;swap(ch[p][0],ch[p][1]);
swap(lef[p][0],rig[p][1]);swap(lef[p][1],rig[p][0]);
}
else if(op==3){
tag3[p]^=1;val[p]=-val[p];
swap(lef[p][0],lef[p][1]);swap(rig[p][0],rig[p][1]);
}
else{
tag1[p]=val[p]=op;tag3[p]=0;
lef[p][0]=rig[p][1]=(val[p]==1?siz[p]:0);
rig[p][0]=lef[p][1]=(val[p]==1?0:siz[p]);
}
}
void push_down(int p){
int lc=ch[p][0],rc=ch[p][1];
if(tag1[p]){if(lc)tag(lc,tag1[p]);if(rc)tag(rc,tag1[p]);tag1[p]=0;}
if(tag2[p]){tag2[p]=0;if(lc)tag(lc,2);if(rc)tag(rc,2);}
if(tag3[p]){tag3[p]=0;if(lc)tag(lc,3);if(rc)tag(rc,3);}
}
int build(int l,int r){
if(l>r)return 0;
int p=l+r>>1;if(s[p]=='(')val[p]=-1;if(s[p]==')')val[p]=1;
ch[p][0]=build(l,p-1);if(ch[p][0])fa[ch[p][0]]=p;
ch[p][1]=build(p+1,r);if(ch[p][1])fa[ch[p][1]]=p;
push_up(p);return p;
}
bool get(int p){return p==ch[fa[p]][1];}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int x,int goal=0){
for(int p=fa[x];p!=goal;p=fa[x]){
if(fa[p]!=goal)rotate(get(p)==get(x)?p:x);
rotate(x);
}if(!goal)rt=x;
}
int kth(int k){
int p=rt;
while(1){
push_down(p);
if(siz[ch[p][0]]>=k)p=ch[p][0];
else if(siz[ch[p][0]]+1==k)return p;
else k-=siz[ch[p][0]]+1,p=ch[p][1];
}
}
void range(int&l,int&r){l=kth(l);r=kth(r+2);splay(l);splay(r,l);}
void update(int l,int r,int op){
range(l,r);tag(ch[r][0],op);
push_up(r);push_up(l);
}
int query(int l,int r){
range(l,r);int p=ch[r][0];
return (lef[p][0]+rig[p][0])/2+(lef[p][0]&1);
}
}cst;
int main(){
scanf("%d%d",&n,&m);
scanf("%s",s+2);
cst.rt=cst.build(1,n+2);
for(int i=1,l,r;i<=m;i++){
scanf("%s",opt);scanf("%d%d",&l,&r);
if(opt[0]=='R'){scanf("%s",ch);cst.update(l,r,ch[0]=='('?-1:1);}
if(opt[0]=='S')cst.update(l,r,2);
if(opt[0]=='I')cst.update(l,r,3);
if(opt[0]=='Q')printf("%d\n",cst.query(l,r));
}
return 0;
}
点击查看I题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,q;char op[3];
int rt[N],len[N],b[N],tot,fa[N*60],ch[N*60][2],val[N*60][2],siz[N*60];
void push_up(int p){siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;}
bool get(int p){return p==ch[fa[p]][1];}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;if(z)ch[z][y==ch[z][1]]=x;
push_up(y);push_up(x);
}
void splay(int id,int x){
for(int p=fa[x];p;p=fa[x]){
if(fa[p])rotate(get(p)==get(x)?p:x);
rotate(x);
}rt[id]=x;
}
void ins(int id,int v,int w){
b[w]=id;++len[id];
if(!rt[id]){
rt[id]=++tot;siz[tot]=1;
val[tot][0]=v;val[tot][1]=w;
return;
}
int p=rt[id],f=0;
while(1){
f=p;p=ch[p][val[p][0]<v];
if(!p){
val[p=++tot][0]=v;val[p][1]=w;siz[p]=1;
fa[p]=f;ch[f][val[f][0]<v]=p;
push_up(f);splay(id,p);break;
}
}
}
void merge(int p,int id){
ins(id,val[p][0],val[p][1]);
if(ch[p][0])merge(ch[p][0],id);
if(ch[p][1])merge(ch[p][1],id);
}
int kth(int id,int k){
int p=rt[id];
while(1){
if(siz[ch[p][0]]>=k)p=ch[p][0];
else{
k-=siz[ch[p][0]]+1;
if(k<=0){splay(id,p);return val[p][1];}
p=ch[p][1];
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,x;i<=n;i++){scanf("%d",&x);ins(i,x,i);}
for(int i=1,x,y;i<=m;i++){
scanf("%d%d",&x,&y);
if(len[b[x]]<len[b[y]])swap(x,y);
merge(rt[b[y]],b[x]);
}
scanf("%d",&q);
for(int i=1,x,y;i<=q;i++){
scanf("%s",op);scanf("%d%d",&x,&y);
if(op[0]=='Q'){
if(len[b[x]]<y)printf("-1\n");
else printf("%d\n",kth(b[x],y));
}
else{
if(len[b[x]]<len[b[y]])swap(x,y);
merge(rt[b[y]],b[x]);
}
}
return 0;
}
Solution Set - Splay的更多相关文章
- NOIP 2017 列队 - Splay - 树状数组
题目传送门 传送点I 传送点II 题目大意 (家喻户晓的题目应该不需要大意) (我之前咋把NOIP 2017打成了NOIP 2018,好绝望) Solution 1 Splay 每行一颗Splay,没 ...
- 【BZOJ-2329&2209】括号修复&括号序列 Splay
2329: [HNOI2011]括号修复 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1007 Solved: 476[Submit][Statu ...
- BZOJ1014:[JSOI2008]火星人(Splay,hash)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...
- SPOJ 3273
传送门: 这是一道treap的模板题,不要问我为什么一直在写模板题 依旧只放代码 Treap 版 //SPOJ 3273 //by Cydiater //2016.8.31 #include < ...
- [HDU1890]RoboticSort
Problem 每次找到最小值,然后把它和它前面的数翻转,然后找第二小数······ 然后输出这些数的下标. Solution 用splay维护,每次找到最小值,然后翻转前面区间. Notice 细节 ...
- [BZOJ3678]wangxz与OJ-[Splay一类的平衡树]
Description 传送门 Solution 直接splay搞定吧..似乎非旋treap也ok? 我已经菜到模板题都写不出来了qaq Code #include<iostream> # ...
- [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)
Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 文本:由0个或 ...
- 【BZOJ-3786】星系探索 Splay + DFS序
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 647 Solved: 212[Submit][Status][Discuss] ...
- 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 806 Solved: 329[Submit][ ...
- 【BZOJ-1014】火星人prefix Splay + 二分 + Hash
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5852 Solved: 1871[Submit] ...
随机推荐
- 什么是GRAY色彩空间
GRAY色彩空间通常指的是灰度图像,灰度图像是一种每个像素都是从黑到白,被处理为256个灰度级别的单色图像.这256个灰度级别分别用区间[0,255]中的数值表示,其中,"0"表示 ...
- AXI自定义IP之UART调试
AXI自定义IP之UART调试 1.实验原理 前面的自定义IP中已经将AXI总线的大部分接口设置都一一验证了.基本掌握了关键接受寄存器slv_reg和发送寄存器data_reg_out,可以基本实现简 ...
- 简单c++构建第一人称
本文内容为UE4.27的文档教程 GameMode确定 新建的项目会自动生成GameMode,如果有更改,而不是使用默认的GameMode类,就需要在引擎的设置中更改 角色的实现 前后左右移动 //前 ...
- C语言 03 原码 反码 补码
原码 计算机中所有的数字都是使用 0 和 1 这样的二进制数来进行表示的. 这时如果要存储一个数据,比如十进制的 3,那么就需要使用 2 个二进制位来保存,二进制格式为 11,占用两个位置,称为 2 ...
- QImage:使用QImage构造函数加载图像和使用成员函数loadFromData加载图像的区别
结论: QImage构造函数,既可以加载内存图像数据,也可以加载二进制文件数据 loadFromData成员函数,只能加载二进制文件数据 loadFromData Qt帮助文档说明 编写测试代码验证 ...
- 基于OT与CRDT协同算法的文档划词评论能力实现
基于OT与CRDT协同算法的文档划词评论能力实现 当我们实现在线文档平台时,划词评论的功能是非常必要的,特别是在重文档管理流程的在线文档产品中,文档反馈是非常重要的一环,这样可以帮助文档维护者提高文档 ...
- 打造美团外卖新体验,HarmonyOS SDK 持续赋能开发者共赢鸿蒙生态
从今年 8 月起,所有升级到 HarmonyOS 4 的手机用户在美团外卖下单后,可通过屏幕上的一个"小窗口",随时追踪到"出餐.取餐.送达"等订单状态.这个能 ...
- 一步一步实现 .NET 8 部署到 Docker
一.前言 本文仅针对操作系统为 CentOS 8 的环境下部署方法进行讲述.如有需要,后续将在其他文章中进行其他系统下的部署方式讲解. 二.准备工作 确保服务器已安装 docker. 可以通过命令 d ...
- Android 开发入门(1)
0x01 准备 (1)概述 安卓(Android)基于 Linux 内核开发的操作系统,由 Google 等领导开发. (2)版本 Android 版本号 API 发布时间 Android 14 - ...
- .NET Emit 入门教程:第六部分:IL 指令:8:详解 ILGenerator 指令方法:类型转换指令
前言: 经过前面几篇的学习,我们了解到指令的大概分类,如: 参数加载指令,该加载指令以 Ld 开头,将参数加载到栈中,以便于后续执行操作命令. 参数存储指令,其指令以 St 开头,将栈中的数据,存储到 ...