BZOJ1901 Dynamic Rankings

区间第K大数终极版、

虽然好似可以主席树、、但是为了锻炼代码能力写了树套树、

果然代码能力就是不行、

不得不承认很少有人的代码会写得比我丑了、、是该改进下了、

 

Code:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

struct point{
	int fa,lson,rson;
	int data,muti,size;
}node[400010];

char od,te;
const int maxn=40010;
int top=0,minnum=9999999,maxnum=-9999999,n,vv,cnt;
int tree[maxn],l[maxn],r[maxn],a[maxn],lt[maxn],rt[maxn];

int newsplay(int key){
	top++;
	node[top].size=node[top].muti=1;
	node[top].lson=node[top].rson=node[top].fa=0;
	node[top].data=key;
	return top;
}

void zig(int now){
	int tf=node[now].fa,te=node[now].size-node[node[now].lson].size;
	if	((node[node[tf].fa].lson)==tf)	
		node[node[tf].fa].lson=now;
	else	node[node[tf].fa].rson=now;
	node[tf].rson=node[now].lson;
	node[now].lson=tf;
	node[now].fa=node[tf].fa;node[tf].fa=now;
	if  (node[tf].rson)  node[node[tf].rson].fa=tf;
	node[now].size=node[tf].size;
	node[tf].size-=te;
}

void zag(int now){
	int tf=node[now].fa,te=node[now].size-node[node[now].rson].size;
	if	((node[node[tf].fa].lson)==tf)	
		node[node[tf].fa].lson=now;
	else	node[node[tf].fa].rson=now;
	node[tf].lson=node[now].rson;
	node[now].rson=tf;
	node[now].fa=node[tf].fa;node[tf].fa=now;
	if  (node[tf].lson) node[node[tf].lson].fa=tf;
	node[now].size=node[tf].size;
	node[tf].size-=te;
}

void splay(int root,int now){
	if  (root==now || node[now].fa==root) return  ;
	while   (root!=node[now].fa){
		if  (node[node[now].fa].fa==root){
	    	if  (node[node[now].fa].lson==now)   zag(now);else   zig(now);
	    	return  ;
		}
		if  (node[node[node[now].fa].fa].lson==node[now].fa)
		    if  (node[node[now].fa].lson==now){zag(now);zag(now);}
		    else	{zig(now);zag(now);}
		else
			if  (node[node[now].fa].lson==now){zag(now);zig(now);}
	    	else	{zig(now);zig(now);}
	}
}

void insert(int now,int key){
	int x=now;
	while   (1){
		node[x].size++;
		if  (node[x].data==key){
			node[x].muti++;
			splay(now,x);
			return  ;
		}
		if  (node[x].data>key){
			if  (!node[x].lson){
				node[x].lson=newsplay(key);
				node[node[x].lson].fa=x;
				splay(now,node[x].lson);
				return  ;
			}else   x=node[x].lson;
		}
		else
		    if  (!node[x].rson){
				node[x].rson=newsplay(key);
				node[node[x].rson].fa=x;
				splay(now,node[x].rson);
				return  ;
		    }else   x=node[x].rson;
	}
}

void deldata(int now,int key){
	int x=now;
    while   (1){
		node[x].size--;
		if  (node[x].data==key){
			node[x].muti--;
			return  ;
		}
		if  (node[x].data>key)  x=node[x].lson;
		else x=node[x].rson;
	}
}

int count(int now,int key){
	int res=0,x=now;
	while   (x){
		if  (node[x].data==key){
			res+=node[x].size-node[node[x].rson].size;
			splay(now,x);
			return res;
		}
		if  (node[x].data>key)  x=node[x].lson;
		else{
			res+=node[x].size-node[node[x].rson].size;
			x=node[x].rson;
		}
	}
	return res;
}

void build(int now,int lm,int rm){
	tree[now]=newsplay(a[lm]);
	l[now]=lm;r[now]=rm;
	if  (lm==rm){
		lt[now]=rt[now]=0;
		return  ;
	}
	for (int i=lm+1;i<=rm;i++){
		insert(tree[now],a[i]);
	}
	build(now*2,lm,(lm+rm)/2);
	build(now*2+1,(lm+rm)/2+1,rm);
	lt[now]=now*2;rt[now]=now*2+1;
}

void query(int now,int lm,int rm,int key){
	if  (l[now]>rm || r[now]<lm)    return  ;
	if  (l[now]>=lm && r[now]<=rm){
		cnt+=count(tree[now],key);
		return  ;
	}
	if  (lt[now])   query(lt[now],lm,rm,key);
	if  (rt[now])   query(rt[now],lm,rm,key);
	return  ;
}

void change(int now,int tar,int ori,int key){
	if  (l[now]>tar || r[now]<tar)  return  ;
	deldata(tree[now],ori);
	insert(tree[now],key);
	if  (l[now]!=r[now]){
		change(lt[now],tar,ori,key);
		change(rt[now],tar,ori,key);
	}
	return  ;
}

void scan(int &x){
	te=getchar();
	while   (te<'0' || te>'9')  te=getchar();
	x=te-'0';te=getchar();
	while   (te>='0' && te<='9'){
		x=x*10+te-'0';
		te=getchar();
	}
}

int main(){
	scanf("%d%d",&n,&vv);
	for (int i=1;i<=n;i++){
		int cl;scan(cl);a[i]=cl;
		minnum=min(minnum,a[i]);
		maxnum=max(maxnum,a[i]);
	}
	scanf("\n");
	build(1,1,n);
	while   (vv--){
		int cl,cr,th;
		od=getchar();
		if  (od=='Q'){
			scan(cl);scan(cr);scan(th);
			int ll=minnum,rr=maxnum;
			while   (ll<rr){
				cnt=0;
				query(1,cl,cr,(ll+rr)/2);
				if  (cnt>=th)   rr=(ll+rr)/2;
				else    ll=(ll+rr)/2+1;
			}
			printf("%d\n",ll);
		}
		else{
			scan(cl);scan(cr);
			minnum=min(minnum,cr);
			maxnum=max(maxnum,cr);
			change(1,cl,a[cl],cr);
			a[cl]=cr;
		}
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/JS-Shining/archive/2013/01/15/2860607.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值