【题意】维护【L,R】区间的逆序对的对数。
【解题方法】最简单的应该是莫队+树状数组了,先分块排序,对于每次更改,如果是更改L,那么应该查询区间内比他小的个数,反之,如果更改R,应该查询区间内比他大的数的个数。第一次写WA了简直无数次,怎么改都是WA,推倒重写过了,好毒啊。
【AC 代码 莫队+BIT】
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=50010;
#define ll long long
int n,m;
int sz,cnt;
int a[maxn];
int pos[maxn];
int X[maxn];
int squre[maxn];
int sum[maxn];
struct Q
{
int l,r;
int id;
} q[maxn];
bool cmp(Q a,Q b){
if(squre[a.l]==squre[b.l])
return a.r<b.r;
return squre[a.l]<squre[b.l];
}
ll ans[maxn];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)
{
while(x<=cnt)
{
sum[x]+=val;
x+=lowbit(x);
}
}
int getsum(int x)
{
int res=0;
while(x){
res+=sum[x];
x-=lowbit(x);
}
return res;
}
int main()
{
while(~scanf("%d",&n))
{
sz=sqrt(n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
X[i]=a[i];
squre[i]=i/sz;
}
sort(X+1,X+1+n);
cnt=unique(X+1,X+1+n)-X-1;
for(int i=1; i<=n; i++)
pos[i]=lower_bound(X+1,X+cnt+1,a[i])-X;
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
memset(sum,0,sizeof(sum));
sort(q+1,q+1+m,cmp);
int L=1,R=0;
ll num=0;
for(int i=1; i<=m; i++)
{
while(R<q[i].r)
{
num+=getsum(cnt)-getsum(pos[++R]);
update(pos[R],1);
}
while(R>q[i].r)
{
num-=getsum(cnt)-getsum(pos[R]);
update(pos[R--],-1);
}
while(L<q[i].l)
{
num-=getsum(pos[L]-1);
update(pos[L++],-1);
}
while(L>q[i].l)
{
num+=getsum(pos[--L]-1);
update(pos[L],1);
}
ans[q[i].id]=num;
}
for(int i=1; i<=m; i++)
printf("%lld\n",ans[i]);
}
return 0;
}