点击这里查看原题
为了使速度最快,每n^(2/3)个数分为一块,处理第i到第j个块的数字k的个数,处理i到j块的前k个数字的个数的平方和。
/*
User:Small
Language:C++
Problem No.:2906
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=5e4+5;
int n,m,q,a[M],pos[M],num[20005],st[40],ed[40],c[40][40][20005],vis[20005],T;
ll ans[40][40][20005],res;
ll ask(int l,int r,int x,int y){
T++;
ll sum=0;
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++){
if(x<=a[i]&&a[i]<=y){
if(vis[a[i]]!=T){
num[a[i]]=0;
vis[a[i]]=T;
}
sum+=2*num[a[i]]+1;
num[a[i]]++;
}
}
return sum;
}
int lp=pos[l]+1,rp=pos[r]-1;
sum=ans[lp][rp][y]-ans[lp][rp][x-1];
for(int i=l;i<=ed[pos[l]];i++){
if(x<=a[i]&&a[i]<=y){
if(vis[a[i]]!=T){
num[a[i]]=c[lp][rp][a[i]];
vis[a[i]]=T;
}
sum+=2*num[a[i]]+1;
num[a[i]]++;
}
}
for(int i=st[pos[r]];i<=r;i++){
if(x<=a[i]&&a[i]<=y){
if(vis[a[i]]!=T){
num[a[i]]=c[lp][rp][a[i]];
vis[a[i]]=T;
}
sum+=2*num[a[i]]+1;
num[a[i]]++;
}
}
return sum;
}
int main(){
freopen("data.in","r",stdin);//
scanf("%d%d%d",&n,&m,&q);
int t=(int)ceil(pow(n,2.0/3));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
pos[i]=(i-1)/t+1;
if(st[pos[i]]==0) st[pos[i]]=i;
ed[pos[i]]=i;
}
for(int i=1;i<=pos[n];i++)
for(int j=i;j<=pos[n];j++)
for(int k=st[i];k<=ed[j];k++)
c[i][j][a[k]]++;
for(int i=1;i<=pos[n];i++)
for(int j=i;j<=pos[n];j++)
for(int k=1;k<=m;k++)
ans[i][j][k]=ans[i][j][k-1]+(ll)c[i][j][k]*c[i][j][k];
while(q--){
ll l,r,x,y;
scanf("%lld%lld%lld%lld",&l,&r,&x,&y);
l^=res;
r^=res;
x^=res;
y^=res;
res=ask(l,r,x,y);
printf("%lld\n",res);
}
return 0;
}