bzoj3744 Gty的妹子序列
Posted AaronPolaris
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3744 Gty的妹子序列相关的知识,希望对你有一定的参考价值。
3744: Gty的妹子序列
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 967 Solved: 293
[Submit][Status][Discuss]
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
1 4 2 3
1
2 4
Sample Output
2
HINT
Source
分块+树状数组+可持久化线段树
如果是离线求区间逆序对数(bzoj3289),可以用莫队+树状数组解决,这道题强制在线显然不能这样做。
考虑分块,f[i][j]表示第i块的起始位置到第j个点的逆序对数,这个可以用树状数组在O(n*sqrt(n)*logn)的复杂度预处理。
然后对于每次询问,如果左右端点在同一块内,树状数组暴力计算。否则找到左端点后面第一个完整的块t,f[t][r]直接统计到答案里,前面剩余的部分,对于每一个位置i,我们要求出[i+1,r]中小于a[i]的数的个数,可以用主席树做。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define pa pair<int,int> #define maxn 50005 #define maxm 1000005 using namespace std; int n,m,tot,cnt,ans,block,T; int a[maxn],s[maxn],num[maxn],rt[maxn],f[250][maxn]; int ls[maxm],rs[maxm],sz[maxm]; pa b[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void add(int x,int y) { for(;x<=tot;x+=(x&(-x))) s[x]+=y; } int sum(int x) { int ret=0; for(;x;x-=(x&(-x))) ret+=s[x]; return ret; } void insert(int x,int &y,int l,int r,int val) { y=++cnt;sz[y]=sz[x]+1; if (l==r) return; ls[y]=ls[x];rs[y]=rs[x]; int mid=(l+r)>>1; if (val<=mid) insert(ls[x],ls[y],l,mid,val); else insert(rs[x],rs[y],mid+1,r,val); } int getans(int x,int y,int l,int r,int L,int R) { if (sz[x]==sz[y]) return 0; if (l==L&&r==R) return sz[y]-sz[x]; int mid=(l+r)>>1; if (R<=mid) return getans(ls[x],ls[y],l,mid,L,R); else if (L>mid) return getans(rs[x],rs[y],mid+1,r,L,R); else return getans(ls[x],ls[y],l,mid,L,mid)+getans(rs[x],rs[y],mid+1,r,mid+1,R); } int query(int x,int y) { int ret=0; if (num[x]==num[y]) { memset(s,0,sizeof(s)); F(i,x,y) ret+=sum(tot)-sum(a[i]),add(a[i],1); return ret; } ret=f[num[x]+1][y]; F(i,x,num[x]*block) ret+=getans(rt[i],rt[y],1,tot,1,a[i]-1); return ret; } int main() { n=read(); block=round(sqrt(n)); F(i,1,n) b[i].first=read(),b[i].second=i; sort(b+1,b+n+1); F(i,1,n) { if (i==1||b[i].first!=b[i-1].first) tot++; a[b[i].second]=tot; } F(i,1,n) insert(rt[i-1],rt[i],1,tot,a[i]); F(i,1,n) num[i]=(i-1)/block+1; F(i,1,num[n]) { memset(s,0,sizeof(s)); F(j,(i-1)*block+1,n) { f[i][j]=f[i][j-1]+sum(tot)-sum(a[j]); add(a[j],1); } } m=read(); F(i,1,m) { int x=read()^ans,y=read()^ans; ans=query(x,y); printf("%d\n",ans); } return 0; }
以上是关于bzoj3744 Gty的妹子序列的主要内容,如果未能解决你的问题,请参考以下文章