思路大概是利用二维数点的思想,在这个数的版本内查询区间,理论时间复杂度应该是 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
*/