版权声明:2333 https://blog.csdn.net/liangzihao1/article/details/82800445
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
分析:
求区间逆序对树。
一种简单的想法,先分块,预处理出
表示从第
块头到位置
的逆序对数,预处理这个是
的。
然后对于一个询问,左边的散块直接找在他后面小于他的数的个数,主席树解决。
代码:
/**************************************************************
Problem: 3744
User: liangzihao
Language: C++
Result: Accepted
Time:10680 ms
Memory:104252 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
const int maxn=5e4+7;
using namespace std;
int n,block,cnt,m;
int a[maxn],b[maxn],c[maxn],bel[maxn],l[231],r[231],root[maxn];
LL sum[231][maxn],ans,x,y;
struct node{
int l,r,data;
}t[maxn*20];
void build_block()
{
block=trunc(sqrt(n));
cnt=n/block+(n%block!=0);
for (int i=1;i<=cnt;i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[cnt]=n;
for (int i=1;i<=n;i++) bel[i]=(i-1)/block+1;
}
void updata(int x,int k)
{
for (int i=x;i<=n;i+=i&(-i)) c[i]+=k;
}
int getsum(int x)
{
int sum=0;
for (int i=x;i>0;i-=i&(-i)) sum+=c[i];
return sum;
}
void ins(int &p,int q,int l,int r,int x)
{
if (!p) p=++cnt;
t[p].data=t[q].data+1;
if (l==r) return;
int mid=(l+r)/2;
if (x<=mid) t[p].r=t[q].r,ins(t[p].l,t[q].l,l,mid,x);
else t[p].l=t[q].l,ins(t[p].r,t[q].r,mid+1,r,x);
}
int getsum(int p,int q,int l,int r,int x,int y)
{
if (t[p].data-t[q].data<=0) return 0;
if ((l==x) && (r==y)) return t[p].data-t[q].data;
int mid=(l+r)/2;
if (y<=mid) return getsum(t[p].l,t[q].l,l,mid,x,y);
else if (x>mid) return getsum(t[p].r,t[q].r,mid+1,r,x,y);
else return getsum(t[p].l,t[q].l,l,mid,x,mid)+getsum(t[p].r,t[q].r,mid+1,r,mid+1,y);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
int size=unique(b+1,b+n+1)-b-1;
for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+size+1,a[i])-b;
build_block();
for (int i=1;i<=n;i+=block)
{
int x=bel[i];
for (int j=i;j<=n;j++)
{
int d=j-i-getsum(a[j]);
sum[x][j]=sum[x][j-1]+(LL)d;
updata(a[j],1);
}
memset(c,0,sizeof(c));
}
for (int i=1;i<=n;i++) ins(root[i],root[i-1],1,n,a[i]);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
x^=ans,y^=ans;
if (l[bel[x]]==x) ans=sum[bel[x]][y];
else
{
ans=sum[bel[x]+1][y];
for (int i=x;i<=min(r[bel[x]],(int)y);i++)
{
ans+=(LL)getsum(root[y],root[i-1],1,n,1,a[i]-1);
}
}
printf("%lld\n",ans);
}
}