Description
我早已习惯你不在身边,
人间四月天 寂寞断了弦。
回望身后蓝天,
跟再见说再见……
某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现她们排成了一个序列,每个妹子有一个美丽度。
Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间[l,r]中妹子们美丽度的逆序对数吗?"
蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线。"
请你帮助一下Autumn吧。
给定一个正整数序列a,对于每次询问,输出al...ar中的逆序对数,强制在线。
Input
第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
第二行包括n个整数a1...an(ai>0,保证ai在int内)。
接下来一行包括一个整数m(1<=m<=50000),表示询问的个数。
接下来m行,每行包括2个整数l、r(1<=l<=r<=n),表示询问al...ar中的逆序
对数(若ai>aj且i<j,则为一个逆序对)。
l,r要分别异或上一次询问的答案(lastans),最开始时lastans=0。
保证涉及的所有数在int内。
Output
对每个询问,单独输出一行,表示al...ar中的逆序对数。
Sample Input
4
1 4 2 3
1
2 4
Sample Output
2
求区间逆序对……
连修改都没有,水题!
我们记f[i][j]为i~j块的总逆序对数,处理散块的时候除了+另一端的贡献,记得把整块的贡献加上~
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4+10,Maxsiz = 233;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
int n,Q,a[N];
int siz,bl[N];
int sum_bigger[Maxsiz][N];//1~i个块大于等于我的个数
int sum_smaller[Maxsiz][N];//i~n个块小与等于的个数
int f[Maxsiz][Maxsiz];//块与块的逆序对总个数
struct SufFix{//后缀和
int c[N];
#define lb(x) (x)&-(x)
inline void add(int x,int k){
for(;x>0;x-=lb(x))c[x]+=k;
}
inline int sum(int x){
int ret=0;
for(;x<=n;x+=lb(x))ret+=c[x];
return ret;
}
}sf;
inline void disc(){
scanf("%d",&n);
Inc(i,1,n)scanf("%d",&a[i]);
int tmp[N];
Inc(i,1,n)tmp[i]=a[i];
sort(tmp+1,tmp+1+n);
int len=unique(tmp+1,tmp+1+n)-tmp-1;
Inc(i,1,n)a[i]=lower_bound(tmp+1,tmp+1+len,a[i])-tmp;
}
inline void init(){
siz=sqrt(n);
Inc(i,1,n)bl[i]=(i-1)/siz+1;
//n√n
Inc(i,1,n)++sum_bigger[bl[i]][a[i]];
Inc(i,1,bl[n]){
Red(j,n,1)sum_bigger[i][j]+=sum_bigger[i][j+1];
Red(j,n,1)sum_bigger[i][j]+=sum_bigger[i-1][j];
}
Inc(i,1,n)++sum_smaller[bl[i]][a[i]];
Red(i,bl[n],1){
Inc(j,1,n)sum_smaller[i][j]+=sum_smaller[i][j-1];
Inc(j,1,n)sum_smaller[i][j]+=sum_smaller[i+1][j];
}
//n√nlogn
Inc(i,1,bl[n]){
memset(sf.c,0,sizeof(sf.c));
int ret=0;
Inc(j,i,bl[n]){
Inc(k,1,siz){
int idx=(j-1)*siz+k;
if(idx>n)break;//防止越界
ret+=sf.sum(a[idx]+1);
sf.add(a[idx],1);
}
f[i][j]=ret;
}
}
}
int las_ans;
inline int Query(int L,int r){
int ret=0;
if(bl[r]-bl[L]<=1){
Inc(i,L,r)ret+=sf.sum(a[i]+1),sf.add(a[i],1);
Inc(i,L,r)sf.add(a[i],-1);
}else {
//左散块 √nlogn
Inc(i,L,bl[L]*siz)ret+=sf.sum(a[i]+1),sf.add(a[i],1);//本身
Inc(i,L,bl[L]*siz)ret+=sum_smaller[bl[L]+1][a[i]-1]-sum_smaller[bl[r]][a[i]-1];//对整块区间的影响
//整块区间 1
ret+=f[bl[L]+1][bl[r]-1];
//右区间 √nlogn
Inc(i,(bl[r]-1)*siz+1,r)ret+=sf.sum(a[i]+1),sf.add(a[i],1);//本身+左散块
Inc(i,(bl[r]-1)*siz+1,r)ret+=sum_bigger[bl[r]-1][a[i]+1]-sum_bigger[bl[L]][a[i]+1];//对整块的影响
//撤销 √nlogn
Inc(i,L,bl[L]*siz)sf.add(a[i],-1);
Inc(i,(bl[r]-1)*siz+1,r)sf.add(a[i],-1);
}
return las_ans=ret;
}
inline void solv(){
memset(sf.c,0,sizeof(sf.c));
scanf("%d",&Q);
while(Q--){
int L,r;scanf("%d%d",&L,&r);
L^=las_ans,r^=las_ans;
if(L>r)swap(L,r);
cout<<Query(L,r)<<"\n";
}
}
int main(){
disc();
init();
solv();
return 0;
}