带修主席树的模板,因为状态不好所以敲了很长时间,不过写完感觉能更好地理解主席树了。

核心其实就是树状数组套主席树,维护方法不再是以前的那种一步一修改,而是对于树状数组上的每一个点建立一棵权值线段树,然后一点一点地维护。这样就从朴素修改后缀所需要的每次\(O(NlogN)\)的复杂度,变成了修改\(log\)棵树所需要的\(O(Nlog^2N)\)。

几个注意事项:

  1. 本题卡常。请使用离散化后的权值进行建树。

  2. 本题卡常。不要用\(cin\)。

  3. 因为是权值线段树,所以要先删除再添加。

  4. 二分的时候也要带上全家桶(\(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的更多相关文章

  1. luogu P2617 Dynamic Rankings && bzoj 1901 (带修改区间第k大)

    链接:https://www.luogu.org/problemnew/show/P2617 思路: 如果直接在主席树上修改的话,每次修改都会对后面所有的树造成影响,一次修改的复杂度就会变成 : n* ...

  2. luogu P2617 Dynamic Rankings(主席树)

    嘟嘟嘟 一句话题意:带修改区间第\(k\)小. 不修改都会,主席树板子.但是有修改就要比较深入的理解主席树了. 众所周知,主席树中以\(i\)为根的线段树维护的是\([1, i]\)这个前缀的权值,因 ...

  3. luogu P2617 Dynamic Rankings(分块,n <= 1e4)

    嘟嘟嘟 带修改区间第k大. 然而某谷把数据扩大到了1e5,所以用分块现在只能得50分. 分块怎么做呢?很暴力的. 基本思想还是块内有序,块外暴力统计. 对于修改,直接重排修改的数所在块,时间复杂度O( ...

  4. Luogu P2617 Dynamic Rankings(整体二分)

    题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...

  5. LUOGU P2617 Dynamic Rankings(树状数组套主席树)

    传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...

  6. [luogu P2617] Dynamic Rankings 带修主席树

    带修改的主席树,其实这种,已经不能算作主席树了,因为这个没有维护可持久化的... 主席树直接带修改的话,由于这种数据结构是可持久化的,那么要相应改动,这个节点以后所有的主席树,这样单次修改,就达到n* ...

  7. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  8. 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 ...

  9. 洛谷P2617 Dynamic Rankings (主席树)

    洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...

随机推荐

  1. python之对字符串类型的数组求平均值

    该字符串是在网页表格中复制的,所以数字间由制表符间隔,先将其转换成列表,再进行统计计算.代码如下: str = "-18.1 -18.3 -18 -18.2 -18 -17.4 -18 -1 ...

  2. 一、linux扩展

    1.linux-解压bz2文件提示tar (child): bzip2: Cannot exec: No such file or directory 原因,linux下没有bzip2解压工具 安装b ...

  3. python排序 sorted()与list.sort() (转)

    该文章为转载:原文地址为:https://www.cnblogs.com/zuizui1204/p/6422939.html 只要是可迭代对象都可以用sorted . sorted(itrearble ...

  4. springboot+jpa+mysql+swagger整合

    Springboot+jpa+MySQL+swagger整合 创建一个springboot web项目 <dependencies> <dependency>      < ...

  5. 3.ansible-iventory的写法和基本变量

    ansible的配置文件一点要多考虑,有些设定比如ssh端口啊用户啊线程啊都尽量在里面调节好iventory的话/etc/ansible/hosts 里面可以使用正则匹配ansible从invento ...

  6. Codeforces 798D Mike and distribution

    题目链接 题目大意 给定两个序列a,b,要求找到不多于个下标,使得对于a,b这些下标所对应数的2倍大于所有数之和. N<=100000,所有输入大于0,保证有解. 因为明确的暗示,所以一定找个. ...

  7. P2123 皇后游戏

    题目背景 还记得 NOIP 2012 提高组 Day1 的国王游戏吗?时光飞逝,光阴荏苒,两年 过去了.国王游戏早已过时,如今已被皇后游戏取代,请你来解决类似于国王游 戏的另一个问题. 题目描述 皇后 ...

  8. css中绝对定位和相对定位详解

    相对定位relative和绝对定位absolute 相对定位 相对定位是标签在根据没加position样式前的位置来定位不会受父级标签的定位的影响,并且定位后不会脱离文本流,会占据原来的位置. 接下来 ...

  9. POJ3261-Milk Patterns-后缀数组

    可重叠重复k次的最长子串长度. 还是使用二分答案对heigh数组分组的做法. #include <cstdio> #include <algorithm> #include & ...

  10. Sudoku POJ - 3076

    Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 5769   Accepted: 2684 Descripti ...