Luogu P2617 Dynamic Rankings
带修主席树的模板,因为状态不好所以敲了很长时间,不过写完感觉能更好地理解主席树了。
核心其实就是树状数组套主席树,维护方法不再是以前的那种一步一修改,而是对于树状数组上的每一个点建立一棵权值线段树,然后一点一点地维护。这样就从朴素修改后缀所需要的每次\(O(NlogN)\)的复杂度,变成了修改\(log\)棵树所需要的\(O(Nlog^2N)\)。
几个注意事项:
本题卡常。请使用离散化后的权值进行建树。
本题卡常。不要用\(cin\)。
因为是权值线段树,所以要先删除再添加。
二分的时候也要带上全家桶(\(lowbit\)对应位)一起修改鸭~
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int INF = 1000000010;
int tot, rt[N];
int n, m, arr[N];
#define mid ((l + r) >> 1)
#define lowbit(x) (x & -x)
struct Segment_Tree {
struct Segment_Node {
int ls, rs, sz;
}t[N << 9];
Segment_Tree () {t[0].sz = 0;}
void modify (int &v, int l, int r, int w, int del) {
if (v == 0) v = ++tot;
t[v].sz += del;
if (l != r) {
if (w <= mid) {
modify (t[v].ls, l, mid + 0, w, del);
} else {
modify (t[v].rs, mid + 1, r, w, del);
}
}
}
}seg;
int cnt, sep[N << 1];
int _sep (int w) {
return lower_bound (sep + 1, sep + 1 + cnt, w) - sep;
}
void change (int pos, int val) {
for (int i = pos; i <= n; i += lowbit (i)) {
seg.modify (rt[i], 0, INF, _sep (arr[pos]), -1);
}
arr[pos] = sep[val];
for (int i = pos; i <= n; i += lowbit (i)) {
seg.modify (rt[i], 0, INF, _sep (arr[pos]), +1);
}
}
int query (int u, int v, int k) {
static int _u[30], _v[30];
// u 到 v 区间第 k 小
int l = 0, r = INF;
_u[0] = _v[0] = 0;
for (int i = u; i != 0; i -= lowbit (i)) _u[++_u[0]] = rt[i];
for (int i = v; i != 0; i -= lowbit (i)) _v[++_v[0]] = rt[i];
while (l < r) {
int lch = 0;
for (int i = 1; i <= _u[0]; ++i) lch -= seg.t[seg.t[_u[i]].ls].sz;
for (int i = 1; i <= _v[0]; ++i) lch += seg.t[seg.t[_v[i]].ls].sz;
if (k <= lch) {
for (int i = 1; i <= _u[0]; ++i) _u[i] = seg.t[_u[i]].ls;
for (int i = 1; i <= _v[0]; ++i) _v[i] = seg.t[_v[i]].ls;
r = mid;
} else {
for (int i = 1; i <= _u[0]; ++i) _u[i] = seg.t[_u[i]].rs;
for (int i = 1; i <= _v[0]; ++i) _v[i] = seg.t[_v[i]].rs;
l = mid + 1;
k -= lch;
}
}
return r;
}
struct Query {
int type, l, r, k, p, w;
}q[N];
int main () {
// cin >> n >> m;
scanf ("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf ("%d", &arr[i]);
sep[++cnt] = arr[i];
}
for (int i = 1; i <= m; ++i) {
static char opt[10];
scanf ("%s", opt);
if (opt[0] == 'Q') {
q[i].type = 0;
scanf ("%d %d %d", &q[i].l, &q[i].r, &q[i].k);
} else {
q[i].type = 1;
scanf ("%d %d", &q[i].p, &q[i].w);
sep[++cnt] = q[i].w;
}
}
sort (sep + 1, sep + 1 + cnt);
cnt = unique (sep + 1, sep + 1 + cnt) - sep - 1; INF = cnt;
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; j += lowbit (j)) {
seg.modify (rt[j], 0, INF, _sep (arr[i]), +1);
}
}
for (int i = 1; i <= m; ++i) {
if (q[i].type == 0) {
printf ("%d\n", sep[query (q[i].l - 1, q[i].r, q[i].k)]);
} else {
change (q[i].p, _sep (q[i].w));
}
}
}
Luogu P2617 Dynamic Rankings的更多相关文章
- luogu P2617 Dynamic Rankings && bzoj 1901 (带修改区间第k大)
链接:https://www.luogu.org/problemnew/show/P2617 思路: 如果直接在主席树上修改的话,每次修改都会对后面所有的树造成影响,一次修改的复杂度就会变成 : n* ...
- luogu P2617 Dynamic Rankings(主席树)
嘟嘟嘟 一句话题意:带修改区间第\(k\)小. 不修改都会,主席树板子.但是有修改就要比较深入的理解主席树了. 众所周知,主席树中以\(i\)为根的线段树维护的是\([1, i]\)这个前缀的权值,因 ...
- luogu P2617 Dynamic Rankings(分块,n <= 1e4)
嘟嘟嘟 带修改区间第k大. 然而某谷把数据扩大到了1e5,所以用分块现在只能得50分. 分块怎么做呢?很暴力的. 基本思想还是块内有序,块外暴力统计. 对于修改,直接重排修改的数所在块,时间复杂度O( ...
- Luogu P2617 Dynamic Rankings(整体二分)
题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...
- LUOGU P2617 Dynamic Rankings(树状数组套主席树)
传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...
- [luogu P2617] Dynamic Rankings 带修主席树
带修改的主席树,其实这种,已经不能算作主席树了,因为这个没有维护可持久化的... 主席树直接带修改的话,由于这种数据结构是可持久化的,那么要相应改动,这个节点以后所有的主席树,这样单次修改,就达到n* ...
- P2617 Dynamic Rankings(树状数组套主席树)
P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...
- 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)
P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...
- 洛谷P2617 Dynamic Rankings (主席树)
洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...
随机推荐
- Eclipse报错:An internal error has occurred. Widget is disposed
win10家庭版报错. 右键Eclipse的快捷方式,在兼容性窗口的兼容模式中,将“以兼容模式运行这个程序”选项打对勾.选择win8就可以解决问题.
- MySQL——安装、配置、启动服务、
1.环境变量配置 将启动连接,加入环境变量中. mysqld :启动服务端 msysql -u 用户名 -p 密码 : 启动客户端 2.windows服务:一直在运行中 E:\wupeiqi\mys ...
- 线程同步Volatile与Synchronized(一)
volatile 一.volatile修饰的变量具有内存可见性 volatile是变量修饰符,其修饰的变量具有内存可见性. 可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改 ...
- Get started with Docker for Windows
Welcome to Docker for Windows! Docker is a full development platform for creating containerized apps ...
- Nginx 4层反向代理
L112 是基于TCP POST_ACCEPT阶段 在建立连接后所做的事情 PREACCESS阶段 limit_conn 限流 与HTTP类似 ACCESS阶段 类似HTTP模块用于控制访问权限 S ...
- 【数学建模】day04-插值与拟合
关于插值原理,这篇文章里总结过. 插值,是在有限个数据点的情况下,模拟出更多的点来适应实际问题的需要. 拟合,是在已知数据点基础上,以已知点处最小误差为标准,模拟出近似函数. 二者有似,实则不同,ma ...
- 【C/C++】c文件重点总结
c文件重点知识总结 程序文件数据文件--->分文本文件(ASCII文件)和映像文件(二进制文件) .区分是用记事本打开后能否看懂. 用二进制文件读写花费时间少,因为用文本文件需要有一个转换的过程 ...
- 关于Binder,作为应用开发者你需要知道的全部
作者:rushjs https://www.jianshu.com/p/062a6e4f5cbe github 地址: https://github.com/rushgit/zhongwenjun.g ...
- Qt 使用openGL 渲染YUV420P格式的视频
代码如下 YUV420P_Render.h #ifndef YUV420P_RENDER_H #define YUV420P_RENDER_H #include <QObject> #in ...
- System.Diagnostics.Process启动Civil 3D及AutoCAD
QQ群友提出问题, 如何启动Civil 3D或者AutoCAD, Kean的博客里有相关的文章 http://through-the-interface.typepad.com/through_the ...