1. 程式人生 > >HNOI2017單旋

HNOI2017單旋

class urn bool ace tree pla ons define 所有

單旋
  • 這道題做法賊多,LCT,splay,線段樹什麽的貌似都行。
  • 像我這種渣渣只會線段樹了(高級數據結構學了也不會用)。
  • 首先離線所有操作,因為不會有兩個點值重復,所以直接離散。
  • 一顆線段樹來維護所有點的深度,並將所有值丟進\(set\)中。
  • 插入操作,在set找到前驅後繼,前驅沒有右兒子就放前驅右兒子,否則放後繼左兒子,同時用\(ch\)\(fa\)假裝模擬樹的形態。
  • 旋轉操作,在\(set\)裏找到節點,可以發現旋轉操作該點兒子深度不變,其他點深度加一,處理一下父子關系,然後線段樹修改區間即可。
  • 刪除操作,先旋轉操作,\(root\)一定只有一個兒子,直接刪掉\(root\)即可,將所有點深度減一

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    typedef int sign;
    typedef long long ll;
    #define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
    #define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
    const int N=1e5+5;
    bool cmax(sign &a,sign b){return
    (a<b)?a=b,1:0;} bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;} template<typename T>inline T read() { T f=1,ans=0; char ch=getchar(); while(!isdigit(ch)&&ch!=‘-‘)ch=getchar(); if(ch==‘-‘)f=-1,ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-‘0‘),ch=getchar(); return
    ans*f; } template<typename T>inline void write(T x,char y) { if(x==0) { putchar(‘0‘);putchar(y); return; } if(x<0) { putchar(‘-‘); x=-x; } static char wr[20]; int top=0; for(;x;x/=10)wr[++top]=x%10+‘0‘; while(top)putchar(wr[top--]); putchar(y); } void file() { #ifndef ONLINE_JUDGE freopen("3721.in","r",stdin); freopen("3721.out","w",stdout); #endif } int n,opt[N][2]; int a[N],top; void input() { n=read<int>(); For(i,1,n) { opt[i][0]=read<int>(); if(opt[i][0]==1)a[++top]=read<int>(),opt[i][1]=a[top]; } } namespace Tree { #define mid ((l+r)>>1) #define lson h<<1,l,mid #define rson h<<1|1,mid+1,r ll lazy[N<<2],sum[N<<2]; void push_down(int h,int l,int r) { if(!lazy[h])return; int ls=h<<1,rs=ls|1; lazy[ls]+=lazy[h];lazy[rs]+=lazy[h]; sum[ls]+=lazy[h]*1ll*(mid-l+1); sum[rs]+=lazy[h]*1ll*(r-mid); lazy[h]=0; } void push_up(int h) { sum[h]=sum[h<<1]+sum[h<<1|1]; } void update(int h,int l,int r,int s,int t,int v) { if(s<=l&&r<=t) { lazy[h]+=v; sum[h]+=1ll*v*1ll*(r-l+1); } else { push_down(h,l,r); if(s<=mid)update(lson,s,t,v); if(mid<t)update(rson,s,t,v); push_up(h); } } int query(int h,int l,int r,int pos) { if(l==r)return sum[h]; push_down(h,l,r); int res; if(pos<=mid)res=query(lson,pos); else res=query(rson,pos); push_up(h); return res; } void modify(int h,int l,int r,int pos,int v) { if(l==r)sum[h]=v; else { push_down(h,l,r); if(pos<=mid)modify(lson,pos,v); else modify(rson,pos,v); push_up(h); } } } set<int>s; set<int>::iterator it; int root,ch[N][2],fa[N]; typedef pair<int,int>pii; #define fir first #define sec second void insert(int x) { int pre,predep; it=s.insert(x).fir; if(!root) { root=x; Tree::modify(1,1,n,x,1); puts("1"); return; } if(it==s.begin()) { ++it;pre=*it; fa[x]=pre;ch[pre][0]=x; } else { --it; if(!ch[*it][1]) { pre=*it; fa[x]=pre; ch[pre][1]=x; } else { ++it;++it; pre=*it; fa[x]=pre; ch[pre][0]=x; } } predep=Tree::query(1,1,n,pre); write(predep+1,\n); Tree::modify(1,1,n,x,predep+1); } void clear(int x) { ch[x][0]=ch[x][1]=fa[x]=0; } void rotate_min() { it=s.begin(); int x=*it; if(x==root){puts("1");return;} int y=ch[x][1],oldroot=root,pre=fa[x]; write(Tree::query(1,1,n,x),\n); if(y)Tree::update(1,1,n,x+1,fa[x]-1,-1); Tree::update(1,1,n,1,n,1); Tree::modify(1,1,n,x,1); root=x; ch[x][1]=oldroot;fa[oldroot]=x; ch[pre][0]=y;fa[y]=pre; } void del_min() { rotate_min(); s.erase(root); Tree::update(1,1,n,1,n,-1); if(!ch[root][0]&&!ch[root][1])clear(root),root=0; else { int oldroot=root; root=ch[root][1]; clear(oldroot);fa[root]=0; } } void rotate_max() { it=s.end();--it; int x=*it; if(x==root){puts("1");return;} write(Tree::query(1,1,n,x),\n); int y=ch[x][0],oldroot=root,pre=fa[x]; if(y)Tree::update(1,1,n,fa[x]+1,x-1,-1); Tree::update(1,1,n,1,n,1); Tree::modify(1,1,n,x,1); root=x; fa[oldroot]=x;ch[x][0]=oldroot; ch[pre][1]=y;fa[y]=pre; } void del_max() { rotate_max(); s.erase(root); Tree::update(1,1,n,1,n,-1); if(!ch[root][0]&&!ch[root][1])clear(root),root=0; else { int oldroot=root; root=ch[root][0]; clear(oldroot);fa[root]=0; } } void work() { sort(a+1,a+top+1); For(i,1,n) { if(opt[i][0]==1) { opt[i][1]=lower_bound(a+1,a+top+1,opt[i][1])-a; insert(opt[i][1]); } else if(opt[i][0]==2)rotate_min(); else if(opt[i][0]==3)rotate_max(); else if(opt[i][0]==4)del_min(); else if(opt[i][0]==5)del_max(); } } int main() { file(); input(); work(); return 0; }

HNOI2017單旋