题意:每次询问区间(l,r)内的逆序对数
思路:莫队算法,利用树状数组进行查询更新
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=50010;
typedef long long LL;
int N,M;
int size,cnt;
int a[maxn];
int X[maxn];
int pos[maxn];
int tree[maxn];
struct Q
{
int l,r;
int id;
bool operator<(const Q &a)const
{
if((l-1)/size==(a.l-1)/size)return (r-1)/size<(a.r-1)/size;
return (l-1)/size<(a.l-1)/size;
}
}q[maxn];
LL ans[maxn];
void update(int x,int val)
{
while(x<=cnt)
{
tree[x]+=val;
x+=(x&(-x));
}
}
int getsum(int x)
{
int sum=0;
while(x)
{
sum+=tree[x];
x-=(x&(-x));
}
return sum;
}
int main()
{
while(scanf("%d",&N)!=EOF)
{
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
X[i]=a[i];
}
size=sqrt(N);
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(tree,0,sizeof(tree));
sort(q+1,q+1+M);
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;
}