bzoj3744 Gty的妹子序列

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

 

正解:分块+树状数组+主席树。

想$O(n\sqrt{n})$的做法,想不出来。。然后看了一眼题解的复杂度。。

$O(n\sqrt{n}logn)$,这不是$mato$的文件管理那题的复杂度吗。。

我真是蠢啊,离线做法都是这样的复杂度,在线怎么会更优秀。。

然后就不是很难做了。

首先,我们将序列分块以后可以预处理出$f[j][i]$,表示第$j$个点到第$i$个块右端点这段区间的逆序对数。这个用树状数组统计,复杂度是$O(n\sqrt{n}logn)$的。

然后,我们再把每个数弄到主席树上(等下会用到的)。

询问的时候,如果$l$和$r$在同一个块上,我们直接用树状数组暴力统计这个区间的逆序对。

如果$l$和$r$不在同一个块上,我们就把区间分开,$l$和$r$的前一个块的右端点分成一个区间,加上对应的$f$值。

然后我们再暴力统计$r$这个块上属于这个区间的点与前面区间的逆序对数。那么我们要统计的就是$l-1$到$i-1$中大于$a[i]$的数的个数,这个就是用刚刚建好的主席树搞就行了。

于是这道题我们就完美地解决了。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define N (50010)
16 #define il inline
17 #define RG register
18 #define ll long long
19 #define lb(x) (x & -x)
20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
21 
22 using namespace std;
23 
24 int sum[20*N],ls[20*N],rs[20*N],rt[N],sz;
25 int f[N][230],c[N],a[N],hsh[N],n,m,tot;
26 int LL[N],RR[N],bl[N],totb,block;
27 ll ans;
28 
29 il int gi(){
30     RG int x=0,q=1; RG char ch=getchar();
31     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
32     if (ch=='-') q=-1,ch=getchar();
33     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
34     return q*x;
35 }
36 
37 il void add(RG int x,RG int v){ for (;x<=tot;x+=lb(x)) c[x]+=v; return; }
38 
39 il int query(RG int x){ RG int res=0; for (;x;x-=lb(x)) res+=c[x]; return res; }
40 
41 il void insert(RG int x,RG int &y,RG int l,RG int r,RG int v){
42     sum[y=++sz]=sum[x]+1,ls[y]=ls[x],rs[y]=rs[x];
43     if (l==r) return; RG int mid=(l+r)>>1;
44     v<=mid?insert(ls[x],ls[y],l,mid,v):insert(rs[x],rs[y],mid+1,r,v);
45 }
46 
47 il int querynxt(RG int x,RG int y,RG int l,RG int r,RG int v){
48     if (l==r) return 0; RG int mid=(l+r)>>1;
49     if (v<=mid) return querynxt(ls[x],ls[y],l,mid,v)+sum[rs[y]]-sum[rs[x]];
50     else return querynxt(rs[x],rs[y],mid+1,r,v);
51 }
52 
53 il void work(){
54     n=gi(),block=sqrt(n),totb=(n-1)/block+1;
55     for (RG int i=1;i<=n;++i){
56     a[i]=gi(),hsh[++tot]=a[i],bl[i]=(i-1)/block+1;
57     if (!LL[bl[i]]) LL[bl[i]]=i; RR[bl[i]]=i;
58     }
59     sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1;
60     for (RG int i=1;i<=n;++i){
61     a[i]=lower_bound(hsh+1,hsh+tot+1,a[i])-hsh;
62     insert(rt[i-1],rt[i],1,tot,a[i]);
63     }
64     for (RG int i=1;i<=totb;++i){
65     for (RG int j=RR[i];j;--j)
66         f[j][i]=f[j+1][i]+query(a[j]-1),add(a[j],1);
67     for (RG int j=RR[i];j;--j) add(a[j],-1);
68     }
69     m=gi(); RG int l,r;
70     while (m--){
71     l=gi()^ans,r=gi()^ans,ans=0;
72     if (bl[l]==bl[r]){
73         for (RG int i=l;i<=r;++i)
74         ans+=query(tot)-query(a[i]),add(a[i],1);
75         for (RG int i=l;i<=r;++i) add(a[i],-1);
76     } else{
77         ans=f[l][bl[r]-1];
78         for (RG int i=LL[bl[r]];i<=r;++i)
79         ans+=querynxt(rt[l-1],rt[i],1,tot,a[i]);
80     }
81     printf("%lld\n",ans);
82     }
83     return;
84 }
85 
86 int main(){
87     File("gty");
88     work();
89     return 0;
90 }

 

posted @ 2017-04-01 20:20  wfj_2048  阅读(217)  评论(0编辑  收藏  举报