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 j\)的数字总数
2
有了这两个信息之后怎么用呢?
考虑一个询问\([l,r]\),
首先,如果左右端点在同一段内,直接暴力即可,
否则,将其拆成三段看待:
-------------------------------------------------
| ① | ② | ③ |
l l所在块的右端点 r所在块的左端点 r
如上图,
逆序对数=
①中的逆序对数+②中的逆序对数+③中的逆序对数+
①与②间的逆序对数+①与③间的逆序对数+②与③间的逆序对数
根据上面预处理出的信息\(f\),
即能直接得到(②+③)一整段的逆序对数,
即②中的逆序对数+③中的逆序对数+②与③间的逆序对数,
复杂度\(O(1)\)
因此,另外要求的就是,
①中的逆序对数+①与②间的逆序对数+①与③间的逆序对数
其中,
①中的逆序对数 及 ①与③间的逆序对数 可以直接树状数组暴力算,
\(\sqrt n\)次插入,\(2*\sqrt n\)次查询,复杂度\(O(\sqrt n*logn)\)
①与②间的逆序对数 则需枚举①中的每个数,然后用预处理出的另一个信息\(s\),
复杂度\(O(\sqrt n*1)\)
3
最后再来讨论一下该如何预处理这两个信息。
\(f[i][j]\):从 第\(i\)块开始位置 到 位置\(j\) 这段区间的逆序对数
对每一块做一次树状数组,复杂度:\(2*(\sqrt n+2\sqrt n+\cdots+n)*logn=O(n\sqrt nlogn)\)
\(s[i][j]\):前\(i\)块中\(\leq j\)的数字总数
算每一块时,充分利用前缀和思想,先算第\(i\)块中\(= j\)的数字总数,再算第\(i\)块中\(\leq j\)的数字总数,最后算前\(i\)块中\(\leq j\)的数字总数,复杂度:\(O(n\sqrt n)\)
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 50010
#define maxb 310
using namespace std;
typedef long long LL;
int a[maxn], mp[maxn], c[maxn], cnt[maxb][maxn], bl[maxn];
int n, m, nn, num, blo;
struct node { int l, r; }b[maxb];
int f[maxb][maxn];
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return x*f;
}
inline int lowbit(int x) { return x & -x;}
inline int query(int x) { int ret=0; while (x) ret += c[x], x-=lowbit(x); return ret; }
inline void add(int x, int v) { while (x<=nn) c[x] += v, x+=lowbit(x); }
void init(int s) {
b[s].l=s*blo, b[s].r=(s==num-1?n:b[s].l+blo);
memset(c, 0, sizeof c);
F(i, b[s].l, n) {
f[s][i] = f[s][i-1] + i-b[s].l-query(a[i]);
add(a[i], 1);
}
F(i, b[s].l, b[s].r) ++cnt[s][a[i]];
F2(i, 1, nn) cnt[s][i] += cnt[s][i-1];
F2(i, 1, nn) cnt[s][i] += cnt[s-1][i];
}
int ask(int l, int r) {
int ret=0;
if (bl[l]==bl[r]) {
memset(c, 0, sizeof c);
F2(i, l, r) {
ret += i-l-query(a[i]);
add(a[i], 1);
}
}
else {
ret += f[bl[l]+1][r];
memset(c, 0, sizeof c);
F(i, l, b[bl[l]].r) {
ret += i-l-query(a[i]);
add(a[i], 1);
ret += cnt[bl[r]-1][a[i]-1]-cnt[bl[l]][a[i]-1];
}
int ex=b[bl[l]].r-l;
F2(i, b[bl[r]].l, r) ret += ex-query(a[i]);
}
return ret;
}
int main() {
scanf("%d", &n); blo = sqrt(n);
F(i, 0, n) a[i]=mp[i]=read(), bl[i]=i/blo;
sort(mp, mp+n);
nn = unique(mp, mp+n)-mp;
F(i, 0, n) a[i] = lower_bound(mp, mp+nn, a[i])-mp+1;
num = bl[n-1]+1;
F(i, 0, num) init(i);
int lastans=0;
scanf("%d", &m);
F(i, 0, m) {
int l=read(),r=read();
l^=lastans, r^=lastans;
--l, --r; if (l>r) swap(l, r);
if (l<0||r>=n) continue;
printf("%d\n", lastans=ask(l,r));
}
return 0;
}
bzoj 3744 Gty的妹子序列 区间逆序对数(在线) 分块的更多相关文章
- BZOJ - 3744 Gty的妹子序列 (区间逆序对数,分块)
题目链接 静态区间逆序对数查询,这道题用线段树貌似不好做,可以把区间分成$\sqrt n$块,预处理出两个数组:$sum[i][j]$和$inv[i][j]$,$sum[i][j]$表示前i个块中小于 ...
- bzoj 3744: Gty的妹子序列 主席树+分块
3744: Gty的妹子序列 Time Limit: 15 Sec Memory Limit: 128 MBSubmit: 101 Solved: 34[Submit][Status] Descr ...
- BZOJ 3744 Gty的妹子序列 (分块 + BIT)
3744: Gty的妹子序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1931 Solved: 570[Submit][Status][Dis ...
- BZOJ 3744: Gty的妹子序列 【分块 + 树状数组 + 主席树】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=3744 3744: Gty的妹子序列 Time Limit: 20 Sec Memory ...
- BZOJ 3744 Gty的妹子序列
Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见-- 某天,蒟蒻Autumn发现了从 Gty的妹子树上掉落下来了许多妹子,他发现 她们排成了一个序 ...
- BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)
题面传送门 题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线 很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献 ...
- BZOJ 3744: Gty的妹子序列 [分块]
传送门 题意:询问区间内逆序对数 感觉这种题都成套路题了 两个预处理$f[i][j]$块i到j的逆序对数,$s[i][j]$前i块$\le j$的有多少个 f我直接处理成到元素j,方便一点 用个树状数 ...
- BZOJ 3744 Gty的妹子序列 做法集结
我只会O(nnlogn)O(n\sqrt nlogn)O(nnlogn)的 . . . . 这是分块+树状数组+主席树的做法O(nnlogn)O(n\sqrt nlogn)O(nnlogn) 搬来 ...
- BZOJ 3744 Gty的妹子序列 分块+树状数组
具体分析见 搬来大佬博客 时间复杂度 O(nnlogn)O(n\sqrt nlogn)O(nnlogn) CODE #include <cmath> #include <cctyp ...
随机推荐
- SpringCloud框架搭建+实际例子+讲解+系列五
(4)服务消费者,面向前端或者用户的服务 本模块涉及到很多知识点:比如Swagger的应用,SpringCloud断路器的使用,服务API的检查.token的校验,feign消费者的使用.大致代码框架 ...
- [Bzoj3894]文理分科(最小割)
Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格子代表一个同学的座位.每位 ...
- spark提交运算原理
前面几天元旦过high了,博客也停了一两天,哈哈,今天我们重新开始,今天我们介绍的是spark的原理 首先先说一个小贴士: spark中,对于var count = 0,如果想使count自增,我们不 ...
- Android面试收集录10 LruCache原理解析
一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大 ...
- https refused 解决方法
今天调试Android程序,所有的手机都ok,后来,我一个手机一直说,refused. 其实这就说明代码是没有问题的,你应该可以根据这个把代码的原因排除.然后剩下的,网络请求还能有什么,网路白. 果然 ...
- 5.bootstrap栅格 清除浮动
只要用到栅格,就注意要清除浮动,清除方法就是在父元素的class上加一个clearfix 1.情景: . <div class="col-sm-7"> <div ...
- 用 Flask 来写个轻博客
用 Flask 来写个轻博客 用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)V ...
- 斐波那契数列(Fibonacci) iOS
斐波那契数列Fibonacci 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2 ...
- 《Cracking the Coding Interview》——第3章:栈和队列——题目5
2014-03-18 05:33 题目:用两个栈来实现一个队列. 解法:栈是反的,队列是正的,反了再反就正过来了.所以,请看代码.操作中时间复杂度有O(1)的,有O(n)的,但均摊下来时间符合O(1) ...
- [网站公告]1月10日1:00-7:00阿里云RDS维护会造成30秒闪断
大家好! 阿里云将于1月10号1:00-7:00(今天夜里)对杭州机房部分RDS实例所在的物理主机做维护操作,维护期间部分RDS实例会有1-2次闪断,每次闪断时间在30秒以内. 我们使用的RDS实例将 ...