luogu P3721 [AH2017/HNOI2017]單旋
阿新 • • 發佈:2022-05-28
題面傳送門
感覺不是很難但就是想了挺久?
首先肯定不能暴力splay單旋,肯定被卡掉。
我們考慮一次單旋有啥性質:可以發現是左子樹深度整體減一,右子樹深度不變,父親和兄弟深度整體加一。
同時父親和兄弟轉了一次之後就變成了右子樹就不變了。
考慮操作二,相當於撇開左子樹不看剩下的就是把除了右子樹之外的點深度加一。
但是這個是最小值根被沒有左子樹啊,所以可以值域上維護一個線段樹,然後二分出右子樹的範圍,就可以區間加了。
後面三個操作同理,第一個操作開個set找前驅後繼就好了。
時間複雜度\(O(n\log n)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define ll long long #define db double #define lb long db #define N (100000+5) #define M ((1<<20)+5) #define Ks (12+5) #define mod 1000000007 #define Mod (mod-1) #define eps (1e-9) #define ull unsigned ll #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) #define Mc(x,y) memcpy(x,y,sizeof(x)) #define d(x,y) (n*(x-1)+(y)) #define R(n) (1ll*rand()*rand()%(n)+1) #define Pc(x) putchar(x) #define LB lower_bound #define UB upper_bound #define PB push_back using namespace std;set<int> F;set<int>::it P1,P2; int n,m,k,x,y,z,Op[N],X[N],Ns[N],Nh; namespace Tree{ #define ls now<<1 #define rs now<<1|1 int Mx[N<<2],Fl[N<<2];I void BD(){Me(Mx,0x3f);}I void Up(int now){Mx[now]=min(Mx[ls],Mx[rs]);} I void PF(int now,int w){Fl[now]+=w;Mx[now]+=w;}I void P(int now){Fl[now]&&(PF(ls,Fl[now]),PF(rs,Fl[now]),Fl[now]=0);} I void Ins(int x,int y,int l=1,int r=Nh,int now=1){if(l==r){Mx[now]=y;return;}P(now);int m=l+r>>1;x<=m?Ins(x,y,l,m,ls):Ins(x,y,m+1,r,rs);Up(now);} I void ADD(int x,int y,int z,int l=1,int r=Nh,int now=1){if(x>y) return;if(x<=l&&r<=y) return PF(now,z);int m=l+r>>1;P(now);x<=m&&(ADD(x,y,z,l,m,ls),0);y>m&&(ADD(x,y,z,m+1,r,rs),0);Up(now);} I int Qry(int x,int l=1,int r=Nh,int now=1){if(l==r) return Mx[now];P(now);int m=l+r>>1;return x<=m?Qry(x,l,m,ls):Qry(x,m+1,r,rs);} I int F1(int x,int l=1,int r=Nh,int now=1){if(l==r) return l-(Mx[now]<x);int m=l+r>>1;P(now);return Mx[ls]>=x?F1(x,m+1,r,rs):F1(x,l,m,ls);} I int F2(int x,int l=1,int r=Nh,int now=1){if(l==r) return l+(Mx[now]<x);int m=l+r>>1;P(now);return Mx[rs]>=x?F2(x,l,m,ls):F2(x,m+1,r,rs);} #undef ls #undef rs } int main(){ freopen("1.in","r",stdin); int i,j;scanf("%d",&n);for(i=1;i<=n;i++) scanf("%d",&Op[i]),Op[i]==1&&(scanf("%d",&X[i]),Ns[++Nh]=X[i]);Tree::BD(); sort(Ns+1,Ns+Nh+1);Nh=unique(Ns+1,Ns+Nh+1)-Ns-1;for(i=1;i<=n;i++) { if(Op[i]==1){ X[i]=LB(Ns+1,Ns+Nh+1,X[i])-Ns;if(F.empty()){Tree::Ins(X[i],1);puts("1");F.insert(X[i]);continue;} P1=P2=F.LB(X[i]);if(P1==F.end()) P2--,Tree::Ins(X[i],z=Tree::Qry(*P2)+1); else if(P1==F.begin()) Tree::Ins(X[i],z=Tree::Qry(*P1)+1); else x=Tree::Qry(*P1),y=Tree::Qry(*(--P2)),Tree::Ins(X[i],z=max(x,y)+1);F.insert(X[i]);printf("%d\n",z); } else if(Op[i]==2||Op[i]==4) printf("%d\n",x=Tree::Qry(*F.begin())),Op[i]^4?(Tree::ADD(Tree::F1(x)+1,Nh,1),Tree::Ins(*F.begin(),1)):(Tree::Ins(*F.begin(),1e9),F.erase(F.begin()),Tree::ADD(1,Tree::F1(x),-1)); else printf("%d\n",x=Tree::Qry(*F.rbegin())),Op[i]^5?(Tree::ADD(1,Tree::F2(x)-1,1),Tree::Ins(*F.rbegin(),1)):(Tree::Ins(*F.rbegin(),1e9),F.erase(*F.rbegin()),Tree::ADD(Tree::F2(x),Nh,-1)); } }