[BZOJ3744]Gty的妹子序列
description
求区间逆序对数,强制在线。
\(n,m\le 10^5\)
sol
分块。预处理出\(ans_{i,j}\)表示第\(i\)个块到第\(j\)个块的答案,\(s_i\)表示插入了前\(i\)个块内所有元素的\(BIT\)。
每次查询的时候开一个临时\(BIT\),对于整块两端的部分,先从右往左加入左边部分(这时候统一计算比自己小的个数),再从左往右加入右边部分(统一计算比自己大的个数)。
时间复杂度\(O(n\sqrt n\log n)\),空间复杂度\(O(n\sqrt 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\n",Ans=query(l,r));
}
return 0;
}