[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
我早已习惯你不在身边,
人间四月天 寂寞断了弦。
回望身后蓝天,
跟再见说再见……
某天,蒟蒻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); } } }
相关文章推荐
- 【分块】【树状数组】bzoj3787 Gty的文艺妹子序列
- bzoj 3744: Gty的妹子序列 主席树+分块
- 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树
- BZOJ 3787: Gty的文艺妹子序列 [分块 树状数组!]
- BZOJ 3744 Gty的妹子序列 分块+树状数组+可持久化线段树
- bzoj 3744: Gty的妹子序列 分块+树状数组
- 【BZOJ3744】Gty的妹子序列-序列分块+树状数组
- BZOJ3787 gty的文艺妹子序列 【树状数组】【分块】
- BZOJ 3744: Gty的妹子序列 [分块]
- 【分块】【树状数组】bzoj3744 Gty的妹子序列
- 【BZOJ3744】Gty的妹子序列 分块+树状数组
- BZOJ 3744 Gty的妹子序列 (分块 + BIT)
- BZOJ 3744: Gty的妹子序列|分块|树状数组
- [BZOJ3809]Gty的二逼妹子序列(莫队+分块)
- bzoj 3809: Gty的二逼妹子序列(莫队算法+分块)
- 【BZOJ-3809】Gty的二逼妹子序列 分块 + 莫队算法
- [bzoj3809]Gty的二逼妹子序列_莫队_分块
- BZOJ 3809 Gty的二逼妹子序列 | 莫队 + 分块
- 【bzoj3809】【GTY的二逼妹子序列】【莫队+分块】
- 【BZOJ 3809】Gty的二逼妹子序列 莫队+分块