1. 程式人生 > >bzoj3065 帶插入區間K小值 替罪羊樹套權值線段樹

bzoj3065 帶插入區間K小值 替罪羊樹套權值線段樹

Description


從前有n只跳蚤排成一行做早操,每隻跳蚤都有自己的一個彈跳力a[i]。跳蚤國王看著這些跳蚤國欣欣向榮的情景,感到非常高興。這時跳蚤國王決定理性愉悅一下,查詢區間k小值。他每次向它的隨從伏特提出這樣的問題: 從左往右第x個到第y個跳蚤中,a[i]第k小的值是多少。
這可難不倒伏特,他在腦袋裡使用函式式線段樹字首和的方法水掉了跳蚤國王的詢問。
這時伏特發現有些跳蚤跳久了彈跳力會有變化,有的會增大,有的會減少。
這可難不倒伏特,他在腦袋裡使用樹狀陣列套線段樹的方法水掉了跳蚤國王的詢問。(orz 主席樹)
這時伏特發現有些遲到的跳蚤會插入到這一行的某個位置上,他感到非常生氣,因為……他不會做了。
請你幫一幫伏特吧。
快捷版題意:帶插入、修改的區間k小值線上查詢。

此題作為一個小小的研究來搞吧~做法有很多~不知道這題究竟有多少種做法。

請自覺O(log^2n),我故意卡塊狀連結串列,塊鏈A了的請受我深情一拜……

A掉的同學請在Discuss裡面簡要說下自己的做法吧~

原序列長度 <= 35000

插入個數 <= 35000,修改個數 <= 70000,查詢個數 <= 70000 ,0 <= 每時每刻的權值 <= 70000

由於是OJ上的題,所以資料無梯度。為了防止卡OJ,本題只有4組資料。

Solution


VFK的題目好勁啊

非常裸的替罪羊樹套權值線段樹。插入就把替罪羊樹路徑上所有線段樹都插入,修改同理。重構就暴力新開線段樹然後暴力插入,這裡需要上垃圾回收。查詢的時候把log棵線段樹摳出來一起二分就行了

以前一直以為很難寫,發現原來是真的很難寫

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)

typedef double db;
const int INF=70000;
const int N=400005;
const db alpha=0.75;

int w[N],wjp[N],yqw[N];

struct
SegTree { struct treeNode {int l,r,sum;} t[N*51]; std:: stack <int> rub; int tot; int new_node() { if (rub.empty()) return ++tot; int top=rub.top(); rub.pop(); return top; } void del(int x) { if (!x) return ; rub.push(x); del(t[x].l); del(t[x].r); t[x].l=t[x].r=t[x].sum=0; } void modify(int &now,int tl,int tr,int x,int v) { if (!now) now=new_node(); t[now].sum+=v; if (tl==tr) return ; int mid=(tl+tr)>>1; if (x<=mid) modify(t[now].l,tl,mid,x,v); else modify(t[now].r,mid+1,tr,x,v); } } ST; struct ScapeTree { struct treeNode {int son[2],fa,size,root;} t[N*2]; int vec[N],root,tot,rec; void push_up(int x) { t[x].size=1; if (t[x].son[0]) t[x].size+=t[t[x].son[0]].size; if (t[x].son[1]) t[x].size+=t[t[x].son[1]].size; } void ins(int x,int k,int nw) { ST.modify(t[x].root,0,INF,w[nw],1); t[x].size++; int z=t[t[x].son[0]].size+1; if (z>=k) { if (!t[x].son[0]) { t[x].son[0]=nw; t[nw].fa=x; t[nw].size=1; ST.modify(t[nw].root,0,INF,w[nw],1); } else ins(t[x].son[0],k,nw); } else { if (!t[x].son[1]) { t[x].son[1]=nw; t[nw].fa=x; t[nw].size=1; ST.modify(t[nw].root,0,INF,w[nw],1); } else ins(t[x].son[1],k-z,nw); } if (t[x].fa&&t[x].size>alpha*t[t[x].fa].size) rec=t[x].fa; } void change(int x,int a,int b) { if (!x) return ; ST.modify(t[x].root,0,INF,a,-1); ST.modify(t[x].root,0,INF,b,1); change(t[x].fa,a,b); } int kth(int k) { for (int x=root;233;) { if (t[t[x].son[0]].size+1==k) return x; if (t[t[x].son[0]].size>=k) x=t[x].son[0]; else { k-=t[t[x].son[0]].size+1; x=t[x].son[1]; } } } void dfs(int x) { if (t[x].son[0]) dfs(t[x].son[0]); vec[++vec[0]]=x; if (t[x].son[1]) dfs(t[x].son[1]); } int build(int l,int r) { int mid=(l+r)>>1,now=vec[mid]; ST.del(t[now].root); t[now].son[0]=t[now].son[1]=t[now].root=t[now].fa=0; if (l!=mid) t[now].son[0]=build(l,mid-1),t[t[now].son[0]].fa=now; if (mid!=r) t[now].son[1]=build(mid+1,r),t[t[now].son[1]].fa=now; rep(i,l,r) ST.modify(t[now].root,0,INF,w[vec[i]],1); push_up(now); return now; } void rebuild() { vec[0]=0; int ff=t[rec].fa,k=t[ff].son[1]==rec; dfs(rec); int tmp=build(1,vec[0]); if (ff) { t[ff].son[k]=tmp; t[tmp].fa=ff; } else root=tmp; rec=0; } void get(int x,int tl,int tr) { if (tr<tl) return ; if (tl==1&&tr==t[x].size) { wjp[++wjp[0]]=t[x].root; return ; } int lxf=t[t[x].son[0]].size; if (tl-lxf-1<1&&tr>lxf) yqw[++yqw[0]]=x; get(t[x].son[0],tl,std:: min(lxf,tr)); get(t[x].son[1],std:: max(tl-lxf-1,1),tr-lxf-1); } } GT; int read() { int x=0,v=1; char ch=getchar(); for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar()); for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar()); return x*v; } int ask(int x,int y,int k) { wjp[0]=yqw[0]=0; GT.get(GT.root,x,y); int l=0,r=INF; for (;l<r;) { int mid=(l+r)>>1,sum=0; rep(i,1,wjp[0]) sum+=ST.t[ST.t[wjp[i]].l].sum; rep(i,1,yqw[0]) sum+=(w[yqw[i]]<=mid&&w[yqw[i]]>=l); if (sum>=k) { rep(i,1,wjp[0]) wjp[i]=ST.t[wjp[i]].l; r=mid; } else { k-=sum; rep(i,1,wjp[0]) wjp[i]=ST.t[wjp[i]].r; l=mid+1; } } return l; } int main(void) { freopen("data.in","r",stdin); freopen("myp.out","w",stdout); int n=read(); rep(i,1,n) w[i]=read(); GT.root=1; GT.t[1].size=1; ST.modify(GT.t[1].root,0,INF,w[1],1); rep(i,2,n) { GT.t[i].size=1; GT.ins(GT.root,i,i); if (GT.rec) GT.rebuild(); } for (int m=read(),lastans=0,ch;m--;) { for (ch=getchar();ch!='I'&&ch!='M'&&ch!='Q';ch=getchar()); int x=read()^lastans,y=read()^lastans; if (ch=='I') { w[++n]=y; GT.ins(GT.root,x,n); if (GT.rec) GT.rebuild(); } else if (ch=='M') { int p=GT.kth(x); GT.change(p,w[p],y); w[p]=y; } else if (ch=='Q') { int k=read()^lastans; printf("%d\n", lastans=ask(x,y,k)); } } return 0; }