解题思路
首先分块预处理,设(sum[i][j])为第(i)块到第(j)块的逆序对数量,(g[i][j])表示前(i)块数值(<=j)的数量,这两个东西是可以(O(nsqrt(n)log(n)))预处理出来的。询问的时候大块直接查询(sum),边角元素之间的贡献直接树状数组,边角元素与大块之间的贡献变成前缀和用(g)数组,时间复杂度(O(nsqrt(n)log(n)))。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=50005;
const int M=300;
inline int rd(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
int n,a[N],cpy[N],lstans,u,num,m,b[N];
int sum[M][M],siz,bl[N],l[M],r[M],g[M][N];
struct BIT{
int f[N];
inline void clear(){
memset(f,0,sizeof(f));
}
inline void add(int x,int k){
for(;x<=u;x+=x&-x) f[x]+=k;
}
inline int query(int x){
int ret=0;
for(;x;x-=x&-x) ret+=f[x];
return ret;
}
}tree;
inline void prework(){
for(int i=1;i<=n;i++) g[bl[i]][a[i]]++;
for(int i=1;i<=num;i++)
for(int j=1;j<=u;j++)
g[i][j]+=g[i][j-1];
for(int i=2;i<=num;i++)
for(int j=1;j<=u;j++)
g[i][j]+=g[i-1][j];
for(int i=1;i<=num;i++){
tree.clear();
for(int j=l[i];j<=n;j++){
sum[i][bl[j]]+=tree.query(u)-tree.query(a[j]);
tree.add(a[j],1);
}
}
for(int i=1;i<=num;i++)
for(int j=i+1;j<=num;j++)
sum[i][j]+=sum[i][j-1];
}
inline int query(int x,int y){
tree.clear(); int ret=0;
if(bl[x]==bl[y]){
for(int i=x;i<=y;i++){
ret+=tree.query(u)-tree.query(a[i]);
tree.add(a[i],1);
}
return ret;
}
ret=sum[bl[x]+1][bl[y]-1];
for(int i=x;i<=r[bl[x]];i++){
ret+=tree.query(u)-tree.query(a[i]);
if(bl[y]-1>bl[x]);
ret+=g[bl[y]-1][a[i]-1]-g[bl[x]][a[i]-1];
tree.add(a[i],1);
}
for(int i=l[bl[y]];i<=y;i++){
ret+=tree.query(u)-tree.query(a[i]);
if(bl[y]-1>bl[x]);
ret+=(g[bl[y]-1][u]-g[bl[x]][u])-(g[bl[y]-1][a[i]]-g[bl[x]][a[i]]);
tree.add(a[i],1);
}
return ret;
}
int main(){
n=rd(); siz=sqrt(n)+1; num=n/siz; if(n%siz) num++;
for(int i=1;i<=n;i++) cpy[i]=a[i]=rd(),bl[i]=(i-1)/siz+1;
for(int i=1;i<=num;i++) l[i]=(i-1)*siz+1,r[i]=i*siz;
sort(cpy+1,cpy+1+n); u=unique(cpy+1,cpy+1+n)-cpy-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(cpy+1,cpy+1+u,a[i])-cpy;
for(int i=1;i<=n;i++) b[i]=a[i];
r[num]=n; prework(); m=rd(); int l,r;
while(m--){
l=rd(),r=rd(); l^=lstans; r^=lstans;
lstans=query(l,r); printf("%d
",lstans);
}
return 0;
}