bzoj3065 带插入区间K小值 替罪羊树套权值线段树

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/85852935

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

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/85852935