【POJ】【P2104&P2761】【题解】【区间K大】【主席树】

传送门:

http://poj.org/problem?id=2104

http://poj.org/problem?id=2761

裸主席树……

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
int a[maxn],b[maxn];
struct node{
	int size;
	node *c[2];
	node(){
		c[0]=c[1]=NULL;size=0;
	}
	void rz(){
		if(c[0])size+=c[0]->size;
		if(c[1])size+=c[1]->size;
	}	
}*Null=new node(),*root[maxn]={NULL};
int tot;
node poor[maxn<<4];
void insert(node *&y,node *&x,int l,int r,int t){
	if(x==NULL)x=Null;
	
	if(tot<(maxn<<4)){
		y=&poor[tot++];
		y->c[0]=y->c[1]=Null;
		y->size=0;
	}else
		y=new node();
	
	int mid=(l+r)>>1;
	if(l==r){
		*y=*x;
		y->size++;
		return;
	}
	if(t<=b[mid]){
		insert(y->c[0],x->c[0],l,mid,t);
		y->c[1]=x->c[1];
		y->rz();
	}else{
		insert(y->c[1],x->c[1],mid+1,r,t);
		y->c[0]=x->c[0];
		y->rz();
	}
}
int kth(node *&x,node *&y,int l,int r,int k){
	if(x==NULL)x=Null;
	if(y==NULL)y=Null;
	if(l==r)return b[l];
	int mid=(l+r)>>1;
	int R=0;
	if(y->c[0])R+=y->c[0]->size;
	if(x->c[0])R-=x->c[0]->size;
	if(R>=k)return kth(x->c[0],y->c[0],l,mid,k);
	else return kth(x->c[1],y->c[1],mid+1,r,k-R);
}
int n,m,size;
int main(){
	Null->c[0]=Null->c[1]=Null;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	size=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++)
		insert(root[i],root[i-1],1,size,a[i]);
	while(m--){
		int l,r,k;
		scanf("%d%d%d",&l,&r,&k);
		printf("%d\n",kth(root[l-1],root[r],1,size,k));
	}
	return 0;
}


新模版:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
inline int lowbit(int x){
	return x&(-x);
}
struct node{
	int size;
	node *c[2];
	node();
	void rz(){
		size=c[0]->size+c[1]->size;
	}
}*Null=new node(),*root[maxn];
node poor[maxn<<4];
int tot;
node::node(){
	size=0;
	c[0]=c[1]=Null;
}
int a[maxn],b[maxn];
void insert(node *&y,node *&x,int l,int r,int t){
	//if(x==NULL)x=Null;
	if(tot<(maxn<<4)){
		y=&poor[tot++];
		y->size=0;y->c[0]=y->c[1]=Null;
	}else	y=new node();
	if(l==r){
		*y=*x;y->size++;return;
	}
	int mid=(l+r)>>1;
	if(t<=b[mid]){
		insert(y->c[0],x->c[0],l,mid,t);
		y->c[1]=x->c[1];
		y->rz();
	}else{
		insert(y->c[1],x->c[1],mid+1,r,t);
		y->c[0]=x->c[0];
		y->rz();
	}
}
int kth(node *&x,node *&y,int l,int r,int k){
	if(l==r)return b[l];
	int mid=(l+r)>>1;
	int R=y->c[0]->size-x->c[0]->size;
	if(R>=k)return kth(x->c[0],y->c[0],l,mid,k);
	else return kth(x->c[1],y->c[1],mid+1,r,k-R);
}
int n,m,size;
int main(){
	Null->size=0;
	Null->c[0]=Null->c[1]=Null;
  	scanf("%d%d",&n,&m);
  	root[0]=Null;
	for(int i=1;i<=n;i++){
		root[i]=Null;
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	size=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++)
		insert(root[i],root[i-1],1,size,a[i]);
	while(m--){
		int l,r,k;
		scanf("%d%d%d",&l,&r,&k);
		printf("%d\n",kth(root[l-1],root[r],1,size,k));
	}	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值