蒟蒻RE求助
查看原帖
蒟蒻RE求助
817925
whileAK楼主2023/8/31 12:41

主席树板子修改下数组大小后复制过来RE了后俩点,看不出哪爆了……

#include<bits/stdc++.h>;
using namespace std;
int n,q,a[300005],c[300005],root[3000005],rel[300005],cnt=0,p=0,x,y,d;
struct ever_tree{
	int lson,rson,ll,rr,counter;
}t[6000005];
int build(int l,int r){//再离散化后的数值上建初始主席树,起初所有节点权值为零 
	++p;//节点编号 
	t[p].ll=l,t[p].rr=r,t[p].counter=0;//区间初始化 
	if(l==r){
		t[p].lson=t[p].rson=0;
		return p;
	}
	int mid=l+r>>1,k=p;//注意用k保存节点编号p 
	t[k].lson=build(l,mid),t[k].rson=build(mid+1,r);//记录左右儿子的编号 
	return k;
}
void mend(int l,int k){//自下向上跟新并新建节点 
	if(t[k].ll==l&&t[k].rr==l){
		t[++p].ll=t[k].ll;t[p].rr=t[k].rr;t[p].counter=t[k].counter+1;
		t[p].lson=t[p].rson=0;
		return;
	}
	++p;
	int mid=t[k].ll+t[k].rr>>1,h=p;//用h记录当前节点编号 
	if(l<=mid){//判断修改点在哪个儿子 
		mend(l,t[k].lson);
		t[h].lson=h+1;t[h].rson=t[k].rson;
	}
	else{
		mend(l,t[k].rson);
		t[h].rson=h+1;t[h].lson=t[k].lson;
	}
	t[h].ll=t[k].ll,t[h].rr=t[k].rr;//记得传递区间范围 
	t[h].counter=t[t[h].lson].counter+t[t[h].rson].counter;//跟新权值 
}
int ask(int k,int g,int w){//询问 
	if(t[k].ll==t[k].rr)return t[k].ll;//找到答案 
	int u=t[t[g].lson].counter-t[t[k].lson].counter;//r版本与l-1版本的主席树权值相减,即为a[l]~a[r]数的分布情况 
	if(u>=w)return ask(t[k].lson,t[g].lson,w);//因为左子树代表的数的范围一定比右子树小 
	else return ask(t[k].rson,t[g].rson,w-u);//所有可以根据左右儿子数的数量,判断答案在哪棵子树 
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i(1);i<=n;++i)scanf("%d",&a[i]);
	memcpy(c,a,sizeof(a));
	sort(c+1,c+n+1);
	c[0]=c[1]-1;
	for(int i(1);i<=n;++i){
		if(c[i]!=c[i-1])rel[++cnt]=c[i];
	}
	for(int i(1);i<=n;++i){
		a[i]=lower_bound(rel+1,rel+cnt+1,a[i])-rel;
	}//离散化 
	build(1,cnt);
	root[0]=1;//第i个个版本的主席树表示区间1~i的数组上,各数值出现的个数
	//如离散化后数组为3,2,2,5,4,1,6,2,1
	//则第5个版本的主席树上代表2~3区间的节点权值为3,即a[1]~a[5]中有3个数在2~3之间 
	for(int i(1);i<=n;++i){
		root[i]=p+1;//依次记录各个版本主席树的根节点 
		mend(a[i],root[i-1]);//把数值a[i]加1 
	}
	while(q--){
		scanf("%d%d%d",&x,&y,&d);
		printf("%d\n",rel[ask(root[x-1],root[y],d)]);//直接查询 
	}
	return 0;
}
2023/8/31 12:41
加载中...