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;
}