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

核心其实就是树状数组套主席树,维护方法不再是以前的那种一步一修改,而是对于树状数组上的每一个点建立一棵权值线段树,然后一点一点地维护。这样就从朴素修改后缀所需要的每次\(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——Flask框架——数据库

    一.数据库框架 Flask-SQLAlchemy (1)安装: pip install flask-sqlalchemy (2)Flask-SQLAlchemy数据库URL 数据库引擎 URL MyS ...

  2. 洛谷 P2119 魔法阵

    题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量. 大魔法师有mm个魔法物品,编号分别为1,2,...,m1,2,...,m.每个物品具有一个魔法值,我们用X_iXi ...

  3. 【数学建模】day04-插值与拟合

    关于插值原理,这篇文章里总结过. 插值,是在有限个数据点的情况下,模拟出更多的点来适应实际问题的需要. 拟合,是在已知数据点基础上,以已知点处最小误差为标准,模拟出近似函数. 二者有似,实则不同,ma ...

  4. FFmpeg 将YUV数据转RGB

    只要开始初始化一次,结束后释放就好,中间可以循环转码 AVFrame *m_pFrameRGB,*m_pFrameYUV; uint8_t *m_rgbBuffer,*m_yuvBuffer; str ...

  5. SQL审计 Yearning 介绍(SQL审核平台)

    yearning SQL 是一个成熟的SQL审计平台

  6. BZOJ4912 SDOI2017天才黑客(最短路+虚树)

    容易想到把边当成点重建图跑最短路.将每条边拆成入边和出边,作为新图中的两个点,由出边向入边连边权为原费用的边.对于原图中的每个点,考虑由其入边向出边连边.直接暴力两两连边当然会被卡掉,注意到其边权是t ...

  7. CF 670C Cinema(算竞进阶习题)

    离散化+排序 离散化统计人数就好,本来不难,但是测试点太丧心病狂了...CF还是大哥啊 #include <bits/stdc++.h> #define INF 0x3f3f3f3f us ...

  8. Codeforces300 F. A Heap of Heaps

    Codeforces题号:#300F 出处: Codeforces 主要算法:树状数组/线段树 难度:4.6 思路分析: 在没看到数据范围之前真是喜出望外,直到发现O(n^2)会被卡…… 其实也不是特 ...

  9. hdu 2844 Coins (多重背包+二进制优化)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2844 思路:多重背包 , dp[i] ,容量为i的背包最多能凑到多少容量,如果dp[i] = i,那么代表 ...

  10. MT【253】仿射和蒙日圆

    如图,设点$M(x_0,y_0)$是椭圆$C:\dfrac{x^2}{2}+y^2=1$上一点,从原点$O$向圆$M:(x-x_0)^2+(y-y_0)^2=\dfrac{2}{3}$作两条切线分别与 ...