ZOJ 2112 Dynamic Rankings

人生第二发树套树。

话说原来树套树跑得比整体二分快啊,真不科学。

整体二分260MS,树套树130MS,快了一倍。

这题嘛就树状数组套主席树。

一开始建一颗空的主席树,以后的树都在这基础上搞。

于是有两套主席树。

第一套是原数组的,依次在前一颗树上建。

第二套是修改出来的主席树,套上树状数组,树状数组修改的时候在之前的树上建。

然后询问的时候要将两套主席树的影响都加上,于是就差不多了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define lb(x) (x&-x)
using namespace std;
const int N=60000+10;
const int M=2500000+10;
int a[N],n,nq,m;
int S[N],T[N],lc[M],rc[M],w[M],cnt;
int hash[N];
void init(){
	sort(hash+1,hash+1+m);
	m=unique(hash+1,hash+1+m)-hash-1;
}
int find(int x){
	return lower_bound(hash+1,hash+m+1,x)-hash;
}
int build(int l,int r){
	int rt=++cnt;
	w[rt]=0;
	if(l!=r){
		int mid=l+r>>1;
		lc[rt]=build(l,mid);
		rc[rt]=build(mid+1,r);
	}
	return rt;
}
int insert(int rt,int pos,int val){
	int nrt=++cnt,tmp=nrt;
	int l=1,r=m;
	w[nrt]=w[rt]+val;
	while(l<r){
		int mid=l+r>>1;
		if(pos<=mid){
			lc[nrt]=++cnt;rc[nrt]=rc[rt];
			nrt=lc[nrt];rt=lc[rt];
			r=mid;
		}else{
			rc[nrt]=++cnt;lc[nrt]=lc[rt];
			nrt=rc[nrt];rt=rc[rt];
			l=mid+1;
		}
		w[nrt]=w[rt]+val;
	}
	return tmp;
}
int use[N];
void add(int x,int p,int d){
	for(;x<=n;x+=lb(x))S[x]=insert(S[x],p,d);
}
int sum(int x){
	int ret=0;
	for(;x>0;x-=lb(x))ret+=w[lc[use[x]]];
	return ret;
}
int query(int a,int b,int k){
	int x=T[a-1],y=T[b];
	int l=1,r=m;
	for(int i=a-1;i;i-=lb(i))use[i]=S[i];
	for(int i=b;i;i-=lb(i))use[i]=S[i];
	while(l<r){
		int mid=l+r>>1;
		int tmp=sum(b)-sum(a-1)+w[lc[y]]-w[lc[x]];
		if(tmp>=k){
			r=mid;
			for(int i=a-1;i;i-=lb(i))use[i]=lc[use[i]];
			for(int i=b;i;i-=lb(i))use[i]=lc[use[i]];
			x=lc[x];y=lc[y];
		}else{
			l=mid+1;
			k-=tmp;
			for(int i=a-1;i;i-=lb(i))use[i]=rc[use[i]];
			for(int i=b;i;i-=lb(i))use[i]=rc[use[i]];
			x=rc[x];y=rc[y];
		}
	}
	return l;
}
struct Query{
	int l,r,k,kind;
}q[10005];
template<class T>void read(T &x){
	static char c;
	static bool f;
	for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
	for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
	if(f)x=-x;
}
int main(){
	int kase;read(kase);
	while(kase--){
		read(n);read(nq);
		cnt=0;m=0;
		for(int i=1;i<=n;i++){
			read(a[i]);hash[++m]=a[i];
		}
		char opt[5];
		for(int i=1;i<=nq;i++){
			scanf("%s",opt);
			if(opt[0]=='Q'){
				read(q[i].l);read(q[i].r);read(q[i].k);
				q[i].kind=1;
			}else{
				read(q[i].l);read(q[i].r);
				q[i].kind=0;
				hash[++m]=q[i].r;
			}
		}
		init();
		T[0]=build(1,m);
		for(int i=1;i<=n;i++)
		T[i]=insert(T[i-1],find(a[i]),1);
		for(int i=1;i<=n;i++)S[i]=T[0];
		for(int i=1;i<=nq;i++){
			if(q[i].kind)printf("%d\n",hash[query(q[i].l,q[i].r,q[i].k)]);
			else{
				add(q[i].l,find(a[q[i].l]),-1);
				add(q[i].l,find(q[i].r),1);
				a[q[i].l]=q[i].r;
			}
		}
	}
	return 0;
}
	


你可能感兴趣的:(ZOJ 2112 Dynamic Rankings)