description
求区间逆序对数,强制在线。
(n,mle 10^5)
sol
分块。预处理出(ans_{i,j})表示第(i)个块到第(j)个块的答案,(s_i)表示插入了前(i)个块内所有元素的(BIT)。
每次查询的时候开一个临时(BIT),对于整块两端的部分,先从右往左加入左边部分(这时候统一计算比自己小的个数),再从左往右加入右边部分(统一计算比自己大的个数)。
时间复杂度(O(nsqrt nlog n)),空间复杂度(O(nsqrt n))。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 5e4+5;
const int M = 250;
int n,m,block,q,a[N],o[N],len,pos[N],L[M],R[M],ans[M][M],s[M][N],tmp[N],Ans;
void add(int k,int v,int *c){
for (int i=k;i<=len;i+=i&-i) c[i]+=v;
}
int sum(int k,int *c){
int res=0;
for (int i=k;i;i-=i&-i) res+=c[i];
return res;
}
void init(){
block=sqrt(n);m=(n-1)/block+1;
for (int i=1;i<=n;++i) pos[i]=(i-1)/block+1;
for (int i=1;i<=m;++i) L[i]=(i-1)*block+1,R[i]=i*block;
R[m]=n;
for (int i=1;i<=m;++i){
int res=0;
for (int j=L[i];j<=n;++j){
res+=sum(len,tmp)-sum(a[j],tmp),add(a[j],1,tmp);
if (j==R[pos[j]]) ans[i][pos[j]]=res;
}
memset(tmp,0,sizeof(tmp));
}
for (int i=1;i<=m;++i){
memcpy(s[i],s[i-1],sizeof(s[i]));
for (int j=L[i];j<=R[i];++j)
add(a[j],1,s[i]);
}
}
int query(int l,int r){
int res=0;
if (pos[r]-pos[l]<=1){
for (int i=l;i<=r;++i)
res+=sum(len,tmp)-sum(a[i],tmp),add(a[i],1,tmp);
for (int i=l;i<=r;++i) add(a[i],-1,tmp);
return res;
}else{
res=ans[pos[l]+1][pos[r]-1];
for (int i=R[pos[l]];i>=l;--i){
res+=sum(a[i]-1,s[pos[r]-1]);
res-=sum(a[i]-1,s[pos[l]]);
res+=sum(a[i]-1,tmp);
add(a[i],1,tmp);
}
for (int i=L[pos[r]];i<=r;++i){
res+=sum(len,s[pos[r]-1])-sum(a[i],s[pos[r]-1]);
res-=sum(len,s[pos[l]])-sum(a[i],s[pos[l]]);
res+=sum(len,tmp)-sum(a[i],tmp);
add(a[i],1,tmp);
}
for (int i=R[pos[l]];i>=l;--i) add(a[i],-1,tmp);
for (int i=L[pos[r]];i<=r;++i) add(a[i],-1,tmp);
return res;
}
}
int main(){
n=gi();
for (int i=1;i<=n;++i) a[i]=o[i]=gi();
sort(o+1,o+n+1);len=unique(o+1,o+n+1)-o-1;
for (int i=1;i<=n;++i) a[i]=lower_bound(o+1,o+len+1,a[i])-o;
init();q=gi();while (q--){
int l=gi()^Ans,r=gi()^Ans;
printf("%d
",Ans=query(l,r));
}
return 0;
}