主席树求调
查看原帖
主席树求调
1039740
hkt486楼主2025/1/8 14:54

思路大概是利用二维数点的思想,在这个数的版本内查询区间,理论时间复杂度应该是 O(nlogn)O(nlogn),但是实际跑上来过不了,所以来求调。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,q,cnt;
struct node{
	int id,val;
}a[N];
struct tre{
	int ls,rs,val;
}tree[N<<8];
bool cmp(node u,node v){
	if(u.val!=v.val)return u.val<v.val;
	return u.id<v.id;
}
int ls(int x){return tree[x].ls;}
int rs(int x){return tree[x].rs;}
void push_up(int x){tree[x].val=tree[ls(x)].val+tree[rs(x)].val;}
void new_node(int x){
	++cnt;
	tree[cnt]=tree[x];
}
int build(int l,int r){
	int x=++cnt;
	if(l==r){
		tree[x].val=0;
		return x;
	}
	int mid=(l+r)>>1;
	tree[x].ls=build(l,mid);
	tree[x].rs=build(mid+1,r);
	return x;
}
int update(int l,int r,int w,int K,int V){
	new_node(w);
	w=cnt;
	if(l==r){
		tree[w].val=V;
		return w;
	}
	int mid=(l+r)>>1;
	if(K<=mid)tree[w].ls=update(l,mid,ls(w),K,V);
	else tree[w].rs=update(mid+1,r,rs(w),K,V);
	push_up(w);
	return w;
}
int query(int l,int r,int w,int L,int R){
	if(L<=l&&r<=R)return tree[w].val;
	int mid=(l+r)>>1,sum=0;
	if(L<=mid)sum+=query(l,mid,ls(w),L,R);
	if(R>mid)sum+=query(mid+1,r,rs(w),L,R);
	return sum;
}
int root[N];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].val;
		a[i].id=i;
	}
	root[0]=build(1,n);
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++){
		root[i]=update(1,n,root[i-1],a[i].id,a[i].val);
	}
	int ans=0;
	cin>>q;
	while(q--){
		int l,r,x;
		cin>>l>>r>>x;
		l^=ans,r^=ans,x^=ans;
		int l1=1,r1=n,id=0;
		while(l1<=r1){
			int mid=(l1+r1)>>1;
			if(x<a[mid].val)r1=mid-1;
			else l1=mid+1,id=mid;
		}
		if(id==0){
			cout<<"0\n";
			continue;
		}
		cout<<(ans=query(1,n,root[id],l,r))<<"\n";
	}
}
/*
8	
2 0 2 4 0 2 0 3
5
1 8 3
10 12 11
3 3 2
3 6 5
12 0 11
*/
2025/1/8 14:54
加载中...