Luogu P3157 [CQOI2011]动态逆序对
这个题有点卡常数。。我的常数比较大所以是吸着氧气跑过去的。。。
题意:计算对于序列中每个位置\(p\),\([1,p-1]\)区间内比它大的数的个数,和\([p + 1, N]\)区间内比它小的数的个数和,要求支持修改操作,带修主席树可以解决。
通过主席树来维护权值状态和比某个数大/小的数的个数,用树状数组来支持修改和维护一个主席树的前缀和(主席树前缀和具有可减性)。时间空间\(O(Nlog^2N)\),\(1000ms+128MB\)的限制对本算法略为苛刻,但卡常可过。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
#define mid ((l + r) >> 1)
#define lowbit(x) (x & -x)
int n, m, tot, rt[N], arr[N], pos[N];
struct Segment_Node {
int sz, ls, rs;
}t[N << 8];
void modify (int &_rt, int l, int r, int w, int del) {
if (_rt == 0) _rt = ++tot;
t[_rt].sz += del;
if (l != r) {
if (w <= mid) {
modify (t[_rt].ls, l, mid, w, del);
} else {
modify (t[_rt].rs, mid + 1, r, w, del);
}
}
}
namespace rev {
int a[N];
inline void add (int pos, int val) {
while (pos <= n) {
a[pos] += val;
pos += lowbit (pos);
}
}
inline int get_sum (int pos) {
register int res = 0;
while (pos) {
res += a[pos];
pos -= lowbit (pos);
}
return res;
}
long long get_rev () {
long long res = 0;
for (int i = n; i >= 1;--i) {
res += get_sum (arr[i]);
add (arr[i], 1);
}
return res;
}
}
int _query (int _rt, int l, int r, int nl, int nr) {
if (nl <= l && r <= nr) return t[_rt].sz;
register int res = 0;
if (nl <= mid) res += _query (t[_rt].ls, l, mid, nl, nr);
if (mid < nr) res += _query (t[_rt].rs, mid + 1, r, nl, nr);
return res;
}
inline int query (int l, int r, int w, int type) {
l = l - 1;
//求序列里面[l, r]内有多少数大于w (type = 1)
//求序列里面[l, r]内有多少数小于w (type = 2)
// printf ("l = %d, r = %d, w = %d, type = %d\n", l, r, w, type);
register int i, res = 0;
for (i = l; i != 0; i -= lowbit (i)) {
if (type == 1) res -= _query (rt[i], 0, n + 1, w + 1, n);
if (type == 2) res -= _query (rt[i], 0, n + 1, 1, w - 1);
}
// printf ("res = %d\n", res);
for (i = r; i != 0; i -= lowbit (i)) {
if (type == 1) res += _query (rt[i], 0, n + 1, w + 1, n);
if (type == 2) res += _query (rt[i], 0, n + 1, 1, w - 1);
}
// printf ("l = %d, r = %d, w = %d, type = %d, res = %d\n", l, r, w, type, res);
return res;
}
inline int read () {
int s = 0, w = 1, ch = getchar ();
while ('9' < ch || ch < '0') {
ch = getchar ();
}
while ('0' <= ch && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar ();
}
return s * w;
}
int main () {
n = read (), m = read ();
register int i, j, w;
for (i = 1; i <= n; ++i) {
arr[i] = read ();
pos[arr[i]] = i;
for (j = i; j <= n; j += lowbit (j)) {
modify (rt[j], 0, n + 1, arr[i], +1);
}
}
long long ans = rev :: get_rev ();
for (i = 1, w = 0; i <= m; ++i) {
printf ("%lld\n", ans);
w = read ();
ans -= query (1, pos[w] - 1, w, 1);
ans -= query (pos[w] + 1, n, w, 2);
for (j = pos[w]; j <= n; j += lowbit (j)) {
modify (rt[j], 0, n + 1, w, -1);
}
}
}
Luogu P3157 [CQOI2011]动态逆序对的更多相关文章
- [Luogu P3157][CQOI2011]动态逆序对 (树套树)
题面 传送门:[CQOI2011]动态逆序对 Solution 一开始我看到pty巨神写这套题的时候,第一眼还以为是个SB题:这不直接开倒车线段树统计就完成了吗? 然后冷静思考了一分钟,猛然发现单纯的 ...
- luogu P3157 [CQOI2011]动态逆序对(CDQ分治)
题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...
- LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)
传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...
- P3157 [CQOI2011]动态逆序对
P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- 洛谷 P3157 [CQOI2011]动态逆序对 解题报告
P3157 [CQOI2011]动态逆序对 题目描述 对于序列\(A\),它的逆序对数定义为满足\(i<j\),且\(A_i>A_j\)的数对\((i,j)\)的个数.给\(1\)到\(n ...
- P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)
P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- 洛谷 P3157 [CQOI2011]动态逆序对(树套树)
题面 luogu 题解 树套树(树状数组套动态开点线段树) 静态使用树状数组求逆序对就不多说了 用线段树代替树状数组,外面套树状数组统计每个点逆序对数量 设 \(t1[i]\)为\(i\)前面有多少个 ...
随机推荐
- php new self()
php里new self() 一般在类内部使用,作用是对自身类实例化 <?php class test{ public function __construct(){ echo ' ...
- Mvc校验用户没有登录就跳转的实现
看字面意思很简单,就是判断用户是否登录了,如果没有登录就跳转到登陆页面. 没错,主要代码如下(这里就不写判断登录了,直接跳转) 首先在控制器中新建一个BaseController public cla ...
- MySQL列类型选择
比如年龄这个字段可以使用 1990-03-15 也可以用 19900315表示在列类型上可以选择 char 和 int:如果一个字段可以选择多种类型,尽量选择一个更快的类型:字段类型优先级 ...
- Jenkins+PowerShell持续集成环境搭建(一)前期准备
0. 系统要求 Windows Server:本文章使用的为Windows Server 2012 JDK:本文章使用为JDK 1.8 Windows PowerShell:本文章使用为PowerSh ...
- 高仿Readhub小程序 微信小程序项目【原】
# News #### 项目介绍微信小程序项目涉及功能 https://gitee.com/richard1015/News https://github.com/richard1015/News 高 ...
- Go语言函数相关
1.函数的声明定义 //func关键字 //getStudent函数名 //(id int, classId int) 参数列表 //(name string,age int) 返回值列表 func ...
- kubernetes 编排详解 资源分配
########给pod 分配cpu和内存资源apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: d ...
- java excel Workbook API
此文摘自:http://blog.sina.com.cn/zenyunhai 1. int getNumberOfSheets() 获得工作薄(Workbook)中工作表(Sheet)的个数,示例: ...
- python第三方库 - dateutil
简介 扩展并增强 datetime 模块的功能.支持 Python 2.3+. 官方文档 : http://labix.org/python-dateutil 安装 两种方法: easy_instal ...
- windows 环境下通过运行快速启动程序
在windows环境下,我们可以使用一些系统内置的快捷键来快速启动我们想要的应用程序,我这里举例几个我经常使用的,比如: 快捷键 功能说明 services.msc 查看系统服务 gpedit.ms ...