1. 程式人生 > >luogu3380 【模板】二逼平衡樹(樹套樹)

luogu3380 【模板】二逼平衡樹(樹套樹)

scanf main pan gtd node body pre turn rotate

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
using namespace std;
int n, m, cnt, a[50005], rot[200005], opt, ans, uu, vv, ww;
struct Node{
    int l, r, siz, hav, val, rnd;
}nd[4000005];
void upd(int k){
    nd[k].siz = nd[nd[k].l].siz + nd[nd[k].r].siz + nd[k].hav;
}
void
lRotate(int &k){ int t=nd[k].r; nd[k].r = nd[t].l; nd[t].l = k; nd[t].siz = nd[k].siz; upd(k); k = t; } void rRotate(int &k){ int t=nd[k].l; nd[k].l = nd[t].r; nd[t].r = k; nd[t].siz = nd[k].siz; upd(k); k = t; } void treapInsert(int &k, int x){ if(!k){ k = ++cnt; nd[k].siz = nd[k].hav = 1
; nd[k].val = x; nd[k].rnd = rand(); return ; } nd[k].siz++; if(nd[k].val==x) nd[k].hav++; else if(nd[k].val>x){ treapInsert(nd[k].l, x); if(nd[nd[k].l].rnd<nd[k].rnd) rRotate(k); } else{ treapInsert(nd[k].r, x); if(nd[nd[k].r].rnd<nd[k].rnd) lRotate(k); } } void
treapDelete(int &k, int x){ if(!k) return ; if(nd[k].val==x){ if(nd[k].hav>1){ nd[k].hav--; nd[k].siz--; return ; } else if(nd[k].l*nd[k].r==0) k = nd[k].l + nd[k].r; else if(nd[nd[k].l].rnd<nd[nd[k].r].rnd) rRotate(k), treapDelete(k, x); else lRotate(k), treapDelete(k, x); } else if(nd[k].val<x) nd[k].siz--, treapDelete(nd[k].r, x); else nd[k].siz--, treapDelete(nd[k].l, x); } int treapQueryRank(int k, int x){ if(!k) return 0; if(nd[k].val>x) return treapQueryRank(nd[k].l, x); else if(nd[k].val<x) return treapQueryRank(nd[k].r, x)+nd[nd[k].l].siz+nd[k].hav; else return nd[nd[k].l].siz; } void treapQueryPre(int k, int x){ if(!k) return ; if(nd[k].val<x) ans = max(ans, nd[k].val), treapQueryPre(nd[k].r, x); else treapQueryPre(nd[k].l, x); } void treapQueryNxt(int k, int x){ if(!k) return ; if(nd[k].val>x) ans = min(ans, nd[k].val), treapQueryNxt(nd[k].l, x); else treapQueryNxt(nd[k].r, x); } void sgtInsert(int o, int l, int r, int x, int k){ treapInsert(rot[o], k); if(l==r) ; else{ int mid=(l+r)>>1; int lson=o<<1; int rson=lson|1; if(x<=mid) sgtInsert(lson, l, mid, x, k); if(mid<x) sgtInsert(rson, mid+1, r, x, k); } } void sgtDelete(int o, int l, int r, int x, int k){ treapDelete(rot[o], k); if(l==r) ; else{ int mid=(l+r)>>1; int lson=o<<1; int rson=lson|1; if(x<=mid) sgtDelete(lson, l, mid, x, k); if(mid<x) sgtDelete(rson, mid+1, r, x, k); } } int sgtQueryRank(int o, int l, int r, int x, int y, int k){ if(l>=x && r<=y) return treapQueryRank(rot[o], k); else{ int mid=(l+r)>>1; int lson=o<<1; int rson=lson|1; int re=0; if(x<=mid) re += sgtQueryRank(lson, l, mid, x, y, k); if(mid<y) re += sgtQueryRank(rson, mid+1, r, x, y, k); return re; } } void sgtQueryPre(int o, int l, int r, int x, int y, int k){ if(l>=x && r<=y) treapQueryPre(rot[o], k); else{ int mid=(l+r)>>1; int lson=o<<1; int rson=lson|1; if(x<=mid) sgtQueryPre(lson, l, mid, x, y, k); if(mid<y) sgtQueryPre(rson, mid+1, r, x, y, k); } } void sgtQueryNxt(int o, int l, int r, int x, int y, int k){ if(l>=x && r<=y) treapQueryNxt(rot[o], k); else{ int mid=(l+r)>>1; int lson=o<<1; int rson=lson|1; if(x<=mid) sgtQueryNxt(lson, l, mid, x, y, k); if(mid<y) sgtQueryNxt(rson, mid+1, r, x, y, k); } } int queryKth(int uu, int vv, int ww){ int l=0, r=100000000, mid, re; while(l<=r){ mid = (l + r) >> 1; if(sgtQueryRank(1, 1, n, uu, vv, mid)+1<=ww) re = mid, l = mid + 1; else r = mid - 1; } return re; } int main(){ srand(time(NULL)); cin>>n>>m; for(int i=1; i<=n; i++){ scanf("%d", &a[i]); sgtInsert(1, 1, n, i, a[i]); } while(m--){ scanf("%d", &opt); if(opt==1){ scanf("%d %d %d", &uu, &vv, &ww); printf("%d\n", sgtQueryRank(1, 1, n, uu, vv, ww)+1); } if(opt==2){ scanf("%d %d %d", &uu, &vv, &ww); printf("%d\n", queryKth(uu, vv, ww)); } if(opt==3){ scanf("%d %d", &uu, &vv); sgtDelete(1, 1, n, uu, a[uu]); a[uu] = vv; sgtInsert(1, 1, n, uu, vv); } if(opt==4){ scanf("%d %d %d", &uu, &vv, &ww); ans = -2147483647; sgtQueryPre(1, 1, n, uu, vv, ww); printf("%d\n", ans); } if(opt==5){ scanf("%d %d %d", &uu, &vv, &ww); ans = 2147483647; sgtQueryNxt(1, 1, n, uu, vv, ww); printf("%d\n", ans); } } return 0; }

luogu3380 【模板】二逼平衡樹(樹套樹)