题解:树套树
不会带修主席树,留坑
#include<iostream> #include<cstdio> #include<cstring> #define lo now<<1 #define ro now<<1|1 using namespace std; const int maxn=20009; const int lgn=40; int n,TT; int ans=0; int h[maxn]; int nn=0; int fa[maxn*lgn]={0},ch[maxn*lgn][2]={0}; int ky[maxn*lgn]={0},siz[maxn*lgn]={0},cnt[maxn*lgn]={0}; void pushup(int x){ siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x]; } int son(int x){ if(ch[fa[x]][0]==x)return 0; else return 1; } void Rotate(int &root,int x){ int y=fa[x]; int z=fa[y]; int b=son(x),c=son(y); int a=ch[x][b^1]; if(z)ch[z][c]=x; else root=x; fa[x]=z; if(a)fa[a]=y; ch[y][b]=a; fa[y]=x;ch[x][b^1]=y; pushup(y);pushup(x); } void Splay(int &root,int x,int i){ while(fa[x]!=i){ int y=fa[x]; int z=fa[y]; if(z==i){ Rotate(root,x); }else{ if(son(x)==son(y)){ Rotate(root,y);Rotate(root,x); }else{ Rotate(root,x);Rotate(root,x); } } } } void Ins(int &root,int val){ int x=root,y=0; while(x){ y=x; if(ky[x]==val){ ++cnt[x];++siz[x]; Splay(root,x,0);return; } if(val>ky[x])x=ch[x][1]; else x=ch[x][0]; } x=++nn; fa[x]=y;siz[x]=cnt[x]=1;ky[x]=val; if(!y){ root=x; }else{ if(ky[x]>ky[y])ch[y][1]=x; else ch[y][0]=x; } Splay(root,x,0); } void Getval(int &root,int val){ int x=root; while(x){ if(ky[x]==val){ Splay(root,x,0); return; } if(val>ky[x])x=ch[x][1]; else x=ch[x][0]; } } void Del(int &root,int val){ Getval(root,val); int x=root; if(cnt[x]>1){ --cnt[x];--siz[x];return; } if((!ch[x][0])&&(!ch[x][1])){ root=0; }else if(!ch[x][0]){ root=ch[x][1]; fa[ch[x][1]]=0; }else if(!ch[x][1]){ root=ch[x][0]; fa[ch[x][0]]=0; }else{ int p=ch[x][0]; while(ch[p][1])p=ch[p][1]; Splay(root,p,x); ch[p][1]=ch[x][1]; fa[ch[x][1]]=p; fa[p]=0;root=p;pushup(p); } } int Getmin(int x,int val){ int ret=0; while(x){ if(ky[x]==val){ return siz[ch[x][0]]+ret; } if(ky[x]<val){ ret+=siz[ch[x][0]]+cnt[x]; x=ch[x][1]; }else{ x=ch[x][0]; } } return ret; } int Getmax(int x,int val){ int ret=0; while(x){ if(ky[x]==val){ return siz[ch[x][1]]+ret; } if(ky[x]>val){ ret+=siz[ch[x][1]]+cnt[x]; x=ch[x][0]; }else{ x=ch[x][1]; } } return ret; } struct SegmentTree{ int l,r,root; }tree[maxn<<2]; void BuildTree(int now,int l,int r){ tree[now].l=l;tree[now].r=r;tree[now].root=0; for(int i=l;i<=r;++i){ Ins(tree[now].root,h[i]); } if(l==r)return; int mid=(l+r)>>1; BuildTree(lo,l,mid); BuildTree(ro,mid+1,r); } void Updatapoint(int now,int pla,int x,int f){ if(f==1)Ins(tree[now].root,x); else Del(tree[now].root,x); if(tree[now].l==tree[now].r)return; int mid=(tree[now].l+tree[now].r)>>1; if(pla<=mid)Updatapoint(lo,pla,x,f); else Updatapoint(ro,pla,x,f); } int Querysec(int now,int ll,int rr,int x,int f){ if(ll>rr)return 0; if(tree[now].l>=ll&&tree[now].r<=rr){ if(f==-1)return Getmin(tree[now].root,x); else return Getmax(tree[now].root,x); } int mid=(tree[now].l+tree[now].r)>>1; int ret=0; if(ll<=mid)ret+=Querysec(lo,ll,rr,x,f); if(rr>mid)ret+=Querysec(ro,ll,rr,x,f); return ret; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&h[i]); BuildTree(1,1,n); for(int i=2;i<=n;++i){ ans=ans+Querysec(1,1,i-1,h[i],1); } printf("%d ",ans); scanf("%d",&TT); while(TT--){ int x,y; scanf("%d%d",&x,&y); if(h[x]==h[y]){ printf("%d ",ans); continue; } if(x>y)swap(x,y); if(h[x]>h[y])--ans; else ++ans; ans+=Querysec(1,x+1,y-1,h[x],1); ans-=Querysec(1,x+1,y-1,h[x],-1); ans+=Querysec(1,x+1,y-1,h[y],-1); ans-=Querysec(1,x+1,y-1,h[y],1); Updatapoint(1,x,h[x],-1); Updatapoint(1,x,h[y],1); Updatapoint(1,y,h[y],-1); Updatapoint(1,y,h[x],1); swap(h[x],h[y]); printf("%d ",ans); } return 0; }