您的位置:首页 > 其它

[BZOJ]3744: Gty的妹子序列 分块+树状数组+主席树

2017-07-16 15:57 351 查看
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

题解:

分块+树状数组+主席树。用ans[i][j]表示第i块左端点到第j个点的逆序对数。对于询问l,r,可以快速得出右边大部分的答案,对于l到所在的块的右端点,可以用主席树求出区间内有多少个数比指定数小。

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50010;
int n,m,belong[maxn],l[250],r[250],a[maxn];
int ans[250][maxn];
struct Num{int x,id;}A[maxn];
bool cmp(Num a,Num b){return a.x<b.x;}
int s[maxn];
int lowbit(int x){return x&-x;}
void add(int x,int y){if(x<=0)return;for(int i=x;i<=n;i+=lowbit(i))s[i]+=y;}
int getsum(int x){int re=0;for(int i=x;i>0;i-=lowbit(i))re+=s[i];return re;}
int z=0,root[maxn],lc[maxn*30],rc[maxn*30],sum[maxn*30];
int q[maxn],hh;
void ins(int &u,int l,int r,int x)
{
if(!u)u=++z;
sum[u]++;
if(l==r)return;
int mid=l+r>>1;
if(x<=mid)ins(lc[u],l,mid,x);
else ins(rc[u],mid+1,r,x);
}
void merge(int &u1,int u2)
{
if(!u1){u1=u2;return;}
if(!u2)return;
sum[u1]+=sum[u2];
merge(lc[u1],lc[u2]);
merge(rc[u1],rc[u2]);
}
int query(int u1,int u2,int l,int r,int ll,int rr)
{
if(!u1&&!u2)return 0;
if(l<=ll&&rr<=r)return sum[u2]-sum[u1];
int mid=ll+rr>>1;
if(r<=mid) return query(lc[u1],lc[u2],l,r,ll,mid);
else if(l>mid) return query(rc[u1],rc[u2],l,r,mid+1,rr);
else return query(lc[u1],lc[u2],l,mid,ll,mid)+query(rc[u1],rc[u2],mid+1,r,mid+1,rr);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&A[i].x),A[i].id=i;
sort(A+1,A+1+n,cmp);
int K=0;A[0].x=-1;
for(int i=1;i<=n;i++)
{
if(A[i].x!=A[i-1].x)K++;
a[A[i].id]=K;
}
int sq=(int)sqrt(n);
for(int i=1;i<=n;i++)
{
belong[i]=(i-1)/sq+1;
r[belong[i]]=i;
if(!l[belong[i]])l[belong[i]]=i;
}
int t=0;
for(int i=1;i<=belong
;i++)
{
memset(s,0,sizeof(s));
ans[i][l[i]]=0;add(a[l[i]],1);
for(int j=l[i]+1;j<=n;j++)
{
ans[i][j]=ans[i][j-1]+(j-l[i]-getsum(a[j]));
add(a[j],1);
}
}
for(int i=1;i<=n;i++)ins(root[i],1,K,a[i]),merge(root[i],root[i-1]);
scanf("%d",&m);
memset(s,0,sizeof(s));
int lastans=0;
while(m--)
{
int L,R;
scanf("%d%d",&L,&R);
L^=lastans,R^=lastans;
if(L>R)swap(L,R);
int bl=belong[L],br=belong[R];
if(bl==br)
{
lastans=0;hh=0;
for(int i=R;i>=L;i--)
{
lastans+=getsum(a[i]-1);
q[++hh]=a[i];add(a[i],1);
}
printf("%d\n",lastans);
for(int i=1;i<=hh;i++)add(q[i],-1);
}
else
{
lastans=ans[bl+1][R];
for(int i=L;i<=r[bl];i++)
lastans+=query(root[i],root[R],1,a[i]-1,1,K);
printf("%d\n",lastans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: