bzoj3744 Gty的妹子序列

我是萌萌的传送门

感觉这题还是不错的……虽然其实算是比较水的题= =

首先分块,令f[i][j]表示第i块到第j块的逆序对数,询问的时候直接计算不完整块与完整块以及不完整块之间的逆序对。

不完整块之间的逆序对直接树状数组暴力求,至于不完整块和完整块的逆序对,我是令s[i]表示前i块的权值前缀和,这样单次查询O(1),可以减小一点常数,代价是空间稍微费了点……

预处理O(nsqrt(n)logn),单次查询O(sqrt(n)logn),空间O(nsqrt(n)),好吧我懒得算如何调节块大小来降低复杂度了,于是就随便找了个233当的块大小= =

细节并不多,然而因为各种脑残错误调了半天才敢交,又因为没看见要离散化和没加强制在线RE两次,真是废了……

 1 /**************************************************************
 2     Problem: 3744
 3     User: hzoier
 4     Language: C++
 5     Result: Accepted
 6     Time:9688 ms
 7     Memory:49700 kb
 8 ****************************************************************/
 9
10 #include<cstdio>
11 #include<cstring>
12 #include<algorithm>
13 using namespace std;
14 const int maxn=50010,B=233,maxb=245;
15 void add(int,int);
16 int query(int);
17 int a[maxn],b[maxn],id[maxn],L[maxb]={0},R[maxb]={0},cntb,f[maxb][maxb]={{0}},s[maxb][maxn]={{0}},c[maxn]={0};
18 int n,m,l,r,lb,rb,ans=0;
19 int main(){
20     scanf("%d",&n);
21     for(int i=1;i<=n;i++){
22         scanf("%d",&a[i]);
23         cntb=id[i]=(i-1)/B+1;
24         if(!L[id[i]])L[id[i]]=i;
25         R[id[i]]=i;
26     }
27     copy(a+1,a+n+1,b+1);
28     sort(b+1,b+n+1);
29     for(int i=1;i<=n;i++)s[id[i]][a[i]=lower_bound(b+1,b+n+1,a[i])-b]++;
30     for(int i=1;i<=cntb;i++){
31         for(int j=1;j<=n;j++)s[i][j]+=s[i-1][j];
32         for(int j=i;j<=cntb;j++){
33             for(int k=L[j];k<=R[j];k++){
34                 f[i][j]+=query(a[k]+1);
35                 add(a[k],1);
36             }
37             f[i][j]+=f[i][j-1];
38         }
39         memset(c,0,sizeof(c));
40     }
41     for(int i=1;i<=cntb;i++)for(int j=1;j<=n;j++)s[i][j]+=s[i][j-1];
42     scanf("%d",&m);
43     while(m--){
44         scanf("%d%d",&l,&r);
45         l^=ans;r^=ans;
46         if(id[l]>=id[r]-1){
47             ans=0;
48             for(int i=l;i<=r;i++){
49                 ans+=query(a[i]+1);
50                 add(a[i],1);
51             }
52             for(int i=l;i<=r;i++)add(a[i],-1);
53         }
54         else{
55             lb=id[l]+1;rb=id[r]-1;
56             ans=f[lb][rb];
57             for(int i=l;i<L[lb];i++){
58                 ans+=query(a[i]+1)+s[rb][a[i]-1]-s[lb-1][a[i]-1];
59                 add(a[i],1);
60             }
61             for(int i=R[rb]+1;i<=r;i++){
62                 ans+=query(a[i]+1)+(s[rb][n]-s[rb][a[i]])-(s[lb-1][n]-s[lb-1][a[i]]);
63                 add(a[i],1);
64             }
65             for(int i=l;i<L[lb];i++)add(a[i],-1);
66             for(int i=R[rb]+1;i<=r;i++)add(a[i],-1);
67         }
68         printf("%d\n",ans);
69     }
70     return 0;
71 }
72 void add(int x,int d){
73     while(x){
74         c[x]+=d;
75         x&=x-1;
76     }
77 }
78 int query(int x){
79     int ans=0;
80     while(x<=n){
81         ans+=c[x];
82         x+=x&-x;
83     }
84     return ans;
85 }

时间: 2024-10-01 15:52:56

bzoj3744 Gty的妹子序列的相关文章

【分块】【树状数组】bzoj3744 Gty的妹子序列

离散化,分块. 预处理出:ans[i][j] 第i块到第j块的逆序对数. f[i][j] 第1~i块中大于j的数的个数. g[i][j] 第1~j块中小于j的数的个数. 每次询问时对于整块部分可以O(1)获得. 对于零散部分呢? >在一列数的后面添加一个数,逆序对数会增加 数列中比它大的数的个数. >在一列数的前面添加一个数,逆序对数会增加 数列中比它小的数的个数. 所以统计以上信息的时候,对于整块的部分,我们可以借由预处理的东西差分来O(1)地获得答案,零散的部分就是树状数组咯. 空间复杂度

bzoj3744: Gty的妹子序列 (BIT &amp;&amp; 分块)

强制在线的区间询问逆序对数 如果不是强制在线 就是可以用莫队乱搞啦 强制在线的话 用f[i][j]记录第i块到第j个点之间的逆序对数 用s[i][j]记录前i块中小于等于j的数字个数 离散化一下 BIT用来处理需要暴力的地方即可 下面是代码 1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 #include <cstring> 5 using namespace std; 6 #d

bzoj 3744: Gty的妹子序列 主席树+分块

3744: Gty的妹子序列 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 101  Solved: 34[Submit][Status] Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹子序列,于是Bakse

BZOJ 3744: Gty的妹子序列

3744: Gty的妹子序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1335  Solved: 379[Submit][Status][Discuss] Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹

【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间 [l,r]中妹子们美丽度的逆序对数吗?" 蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线." 请你帮助一下Autumn吧.

【bzoj3744】GTY的妹子序列

大力分块+树状数组+主席树-- #include<bits/stdc++.h> #define N 50005 #define pa pair<int,int> #define fi first #define sc second using namespace std; int n,m,cnt,tot,size,t; int a[N],c[N],num[N],rt[N]; int sum[250][N]; inline int lowbit(int x){return (x&am

BZOJ 3744 Gty的妹子序列 分块+fenwick

题目大意:强制在线区间无修改逆序对. 思路:看到数据范围发现分块是很显然的.预处理了很多东西,比如说每个块里面的逆序对个数,还有f[i][j]表示从第i块到第j块的逆序对个数.如果仅仅处理到这里的话,后面是不太好处理的.我们还需要一个东西,是每个点对每个块的逆序对个数,并取前缀合优化.否则的话就得用主席树来乱搞,那常数 反正总时间复杂度大概是O(n*sqrt(n)*logn)  强行不到O(n^2) 剩下就是小事了, 比如离散话啥的.. CODE: #include <cmath> #incl

BZOJ 3744: Gty的妹子序列 [分块]

传送门 题意:询问区间内逆序对数 感觉这种题都成套路题了 两个预处理$f[i][j]$块i到j的逆序对数,$s[i][j]$前i块$\le j$的有多少个 f我直接处理成到元素j,方便一点 用个树状数组就行了 预处理和查询都带$log$所以还是开根号n比较科学吧 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath>

bzoj 3744 Gty的妹子序列 区间逆序对数(在线) 分块

题目链接 题意 给定\(n\)个数,\(q\)个询问,每次询问\([l,r]\)区间内的逆序对数. 强制在线. 思路 参考:http://www.cnblogs.com/candy99/p/6579556.html 离线的话就如上一题bzoj 3289 Mato的文件管理,可以直接用 莫队 搞,在线的话怎么办呢? 分块大法好. 1 预处理出两个信息: \(f[i][j]\):从 第\(i\)块开始位置 到 位置\(j\) 这段区间的逆序对数 \(s[i][j]\):前\(i\)块中\(\leq