模版:替罪羊树
文章目錄
- 前言
- 注意事項
- 代碼
所謂替罪羊樹,就是有一頭替罪羊的樹
(逃)
前言
在看完了一大堆各種平衡樹的教程之后,決定學一個這個
因為它有一個很關鍵的好處:無須旋轉
可以在pushup復雜度太惡心的題中做到splay做不到的事情
比如平衡樹套線段樹
但是在區間問題中還是splay最強啦!
注意事項
代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline const int N=5e6+100; const int M=150; const int mod=998244353; inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n,m; int ls[N],rs[N],siz[N],val[N],cnt[N],de[N],tot,rub[N],top,r; int q[N],num,o[N]; il int New(int v,int oo){int x=top?rub[top--]:++tot;ls[x]=rs[x]=0;siz[x]=cnt[x]=oo;val[x]=v;de[x]=0;return x; } il void pushup(int x){siz[x]=siz[ls[x]]+siz[rs[x]]+cnt[x];de[x]=cnt[x]?0:1;if(ls[x]) de[x]+=de[ls[x]];if(rs[x]) de[x]+=de[rs[x]];return; } il int build(int l,int r){if(l>r) return 0;int mid=(l+r)>>1;int k=New(q[mid],o[mid]);ls[k]=build(l,mid-1);rs[k]=build(mid+1,r);pushup(k);return k; } il void pia(int x){if(!x) return;pia(ls[x]);if(cnt[x]){q[++num]=val[x];o[num]=cnt[x];}pia(rs[x]);rub[++top]=x;return; } const double A=0.7; il void check(int &x){if(!cnt[x]) return;if(siz[x]*A<siz[ls[x]]||siz[x]*A<siz[rs[x]]||siz[x]<=de[x]){num=0;pia(x);x=build(1,num);}return; } il void ins(int &k,int v){if(!k){k=New(v,1);return;}if(v==val[k]){cnt[k]++;pushup(k);return;}else if(v<=val[k]) ins(ls[k],v);else ins(rs[k],v);pushup(k);check(k);return; } il void del(int k,int v){if(!k) return;if(v==val[k]){cnt[k]--;pushup(k);return;}if(v<val[k]) del(ls[k],v);else del(rs[k],v);pushup(k);check(k);return; } il int findrnk(int k,int v){if(!k) return 1;if(v==val[k]) return siz[ls[k]]+1;else if(v<val[k]) return findrnk(ls[k],v);else return siz[ls[k]]+cnt[k]+findrnk(rs[k],v); } il int findnth(int k,int kth){//printf("k=%d kth=%d\n",k,kth);if(kth<=siz[ls[k]]) return findnth(ls[k],kth);else if(kth<=siz[ls[k]]+cnt[k]) return val[k];else return findnth(rs[k],kth-siz[ls[k]]-cnt[k]); } il int findpre(int x){//printf("rnk=%d\n",findrnk(r,x));return findnth(r,findrnk(r,x)-1); } il int findnxt(int x){return findnth(r,findrnk(r,x+1)); } void print(int k){if(!k) return;printf("k=%d val=%d ls=%d rs=%d siz=%d cnt=%d\n",k,val[k],ls[k],rs[k],siz[k],cnt[k]);print(ls[k]);print(rs[k]);if(k==r) putchar('\n'); } int main(){n=read();for(int i=1;i<=n;i++){int op=read(),x=read();switch(op){case 1:{ins(r,x);break;}case 2:{del(r,x);break;}case 3:{printf("%d\n",findrnk(r,x));break;}case 4:{printf("%d\n",findnth(r,x));break;}case 5:{printf("%d\n",findpre(x));break;}case 6:{printf("%d\n",findnxt(x));break;}}//print(r);}return 0; } /* 9 1 10 1 10 1 15 3 5 */總結
- 上一篇: win8安装系统教程
- 下一篇: 如何创建html网页