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\)前面有多少个 ...
随机推荐
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0'
七月 05, 2018 10:26:54 上午 org.apache.tomcat.util.digester.SetPropertiesRule begin警告: [SetPropertiesRul ...
- Codeforces#543 div2 A. Technogoblet of Fire(阅读理解)
题目链接:http://codeforces.com/problemset/problem/1121/A 真·阅读理解 题意就是 有n个人 pi表示他们的强度 si表示他们来自哪个学校 现在Arkad ...
- c++ 实现哈夫曼树中遇见的问题
为了提高效率求得 叶子 节点中权值最小的两个元素,我们需要使用堆数据结构,它可以以O(logn)的复杂度 取得n个元素中的最小元素.为了绕过堆的实现,我们可以使用标准模板库中相应的标准模板—优先队列. ...
- hdu-2717(基础搜索bfs)
题意:给你n和k,问你n最少花费多少代价能得到k: 有两种变换:1.n++或者n--: 2.n=n*2: 两种代价每次的花费都是1: 思路:一维的bfs,每次入队三个点,一个是n+1,一个是n-1,一 ...
- sws_getContext函数参数介绍
原型: SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, ...
- javadoc格式化,解决多个形参空格暴多,页面溢出问题
格式化前: 格式化后: pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xml ...
- 微信小程序——demo合集及简单的文档解读【五】
官方Demo https://github.com/wechat-miniprogram/miniprogram-demo 其他Demo https://www.cnblogs.com/ytkah/p ...
- Sum of Consecutive Prime Numbers POJ - 2739 线性欧拉筛(线性欧拉筛证明)
题意:给一个数 可以写出多少种 连续素数的合 思路:直接线性筛 筛素数 暴力找就行 (素数到n/2就可以停下了,优化一个常数) 其中:线性筛的证明参考:https://blog.csdn.net ...
- 【XSY2773】基因 后缀平衡树 树套树
题目描述 有一棵树,每条边上面都有一个字母.每个点还有一个特征值\(a_i\). 定义一个节点\(i\)对应的字符串为从这个点到根的路径上所有边按顺序拼接而成的字符串\(s_i\). 有\(m\)次操 ...
- 05 Zabbix4.0触发器表达式Trigger expression支持的函数
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 05 Zabbix4.0触发器表达式Trigger expression支持的函数 所有函数返回值 ...