带修改离线主席树 + 树状数组 ZOJ - 2112【Dynamic Rankings】

https://cn.vjudge.net/contest/304073#problem/E

题意

给定 n 个数和 m 次操作,操作分为两种:

  • Q x y z —— 询问 [x, y] 区间里的第 z 小的数

  • C x y —— 把第 x 个数变成 y

分析

mmp突然想起来可以分块...

这题属于带修改的主席树,需要用到树状数组维护。

如果用普通静态主席树的做法,每次更新都需要把 “该数所在树和之后的所有树” 都进行更新(由于前缀的性质),这样更新的最坏总复杂度为 \(O(n*m)\) 显然不行。

但是可以发现,对于改变 i 位置的值来说,对于 “该数所在树和之后的所有树” 的影响是相同的。因此只要在原来的基础上增加一类树,用于维护更新掉的数,所以我们可以用树状数组来记录更新,每次更新 \(log(n)\) 棵树。

因此我们需要用到离线来做,把题目所给定的所有修改后的值也加入 \(vector\) 中。第一轮建树的时候只需要把修改前的所有值进行建树。

对于更新,我们不改变这些已经建好的树,而是另建一类树S,用来记录更新。用树状数组来维护,也就是树状数组的每个节点都是一颗线段树。初始时,S[0]、S[1]、S[2]、S[3](树状数组的每个节点)这些都与 root[0] 相同(也就是空树 0)。

对于 (C 2 6)操作来说,我们只需要减去 2 ,加上 6 即可。对于减去2(树状数组 \(i+lowbit(i)\) 为 i 的父亲节点, 修改 i,就要把 i 的所有父亲节点都修改了)。因此要更新的是 S[2] 和 S[4] 这两个节点。

当查询的时候, \(sum\) 需要另外再加上 S树 的值之差。

代码

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;const int maxn = 5e4+5;int n, m, cnt;
int root[maxn];
int a[maxn];
vector<int> v;
int new_n;
int S[maxn];    // 树状数组维护的新树
int use[maxn];  // use记录要操作的线段树下标struct node {int l, r, sum;
}T[maxn*40];struct Question {int f;int a, b, c;
}Q[maxn];void init() {v.clear();memset(root, 0, sizeof(root));for(int i = 0; i <= n*40; i++) {T[i].l = T[i].r = T[i].sum = 0;}cnt = 0;
}int getid(int x) {return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}int lowbit(int x) {return x & (-x);
}void build(int l, int r, int &rt) {rt = ++cnt;if(l == r) {return ;}int mid = (l+r) / 2;build(l, mid, T[rt].l);build(mid+1, r, T[rt].r);
}void update(int l, int r, int &x, int y, int pos, int f) {T[++cnt] = T[y];T[cnt].sum += f;    // 1 or -1x = cnt;if(l == r)return ;int mid = (l+r) / 2;if(mid >= pos) {update(l, mid, T[x].l, T[y].l, pos, f);}else {update(mid+1, r, T[x].r, T[y].r, pos, f);}
}void Add(int x, int c, int f) {while(x <= n) {update(1, new_n, S[x], S[x], c, f);x += lowbit(x);}
}int Sum(int x) {int ans = 0;while(x > 0) {ans += T[T[use[x]].l].sum;x -= lowbit(x);}return ans;
}int query(int l, int r, int a, int b, int x, int y, int k) {if(l == r) {return l;}int mid = (l+r) / 2;int sum = Sum(b) - Sum(a) + T[T[y].l].sum - T[T[x].l].sum;if(sum >= k) {for(int i = a; i > 0; i -= lowbit(i)) {use[i] = T[use[i]].l;}for(int i = b; i > 0; i -= lowbit(i)) {use[i] = T[use[i]].l;}return query(l, mid, a, b, T[x].l, T[y].l, k);}else {for(int i = a; i > 0; i -= lowbit(i)) {use[i] = T[use[i]].r;}for(int i = b; i > 0; i -= lowbit(i)) {use[i] = T[use[i]].r;}return query(mid+1, r, a, b, T[x].r, T[y].r, k-sum);}
}int main() {// fopen("in.txt", "r", stdin);// fopen("out.txt", "w", stdout);int t;scanf("%d", &t);while(t--) {init();scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%d", &a[i]);v.push_back(a[i]);}for(int i = 1; i <= m; i++) {char f[10];scanf("%s", f);if(f[0] == 'Q') {int l, r, k;scanf("%d%d%d", &l, &r, &k);Q[i].f = 0;Q[i].a = l;Q[i].b = r;Q[i].c = k;}else {int x, c;scanf("%d%d", &x, &c);Q[i].f = 1;Q[i].a = x;Q[i].b = c;v.push_back(c);}}sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()), v.end());new_n = (int)v.size();for(int i = 1; i <= n; i++) {update(1, new_n, root[i], root[i-1], getid(a[i]), 1);}for(int i = 1; i <= n; i++) {S[i] = root[0];}for(int i = 1; i <= m; i++) {if(Q[i].f == 0) {for(int j = Q[i].a-1; j > 0; j-= lowbit(j)) {use[j] = S[j];}for(int j = Q[i].b; j > 0; j -= lowbit(j)) {use[j] = S[j];}int ans = query(1, new_n, Q[i].a-1, Q[i].b, root[Q[i].a-1], root[Q[i].b], Q[i].c) - 1;printf("%d\n", v[ans]);}else {Add(Q[i].a, getid(a[Q[i].a]), -1);  // 减去修改前的值Add(Q[i].a, getid(Q[i].b), 1);   // 加上新值a[Q[i].a] = Q[i].b;}}}return 0;
}

转载于:https://www.cnblogs.com/Decray/p/10928452.html

带修改离线主席树 + 树状数组 ZOJ - 2112【Dynamic Rankings】相关推荐

  1. ZOJ 2112 Dynamic Rankings(主席树-动态第k大)

    Description 给出一个长度为n的序列a,两种操作 C x v:将第x个元素的值改成v Q l r k:查询区间[l,r]中第k大的元素 Input 第一行为一个整数t表示用例组数,每组用例第 ...

  2. bzoj 1901: Zju2112 Dynamic Rankings(离线树状数组+主席树)

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 8144  Solved: 3378 [ ...

  3. zoj - 2112 带修改主席树 + 空间优化

    ZOJ - 2112 题意:求区间第k小 思路:带修改区间第k小裸题,无修改的主席树是维护一个前缀线段树,每次更新log个节点,用root 和 ls rs作为每颗前缀线段树的根节点和左右子树的索引(相 ...

  4. P2617 Dynamic Rankings(主席树+树状数组)

    怕是还没有题解,所以先写一篇. 这题就是维护带修改的主席树.首先树套树肯定是能做的,既然树套树能做那么整体二分肯定也是可以的. 由于我并没有使用这两种做法,所以此处不予介绍. 大概描述下主席树的思路: ...

  5. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  6. 高级数据结构1—初识树状数组—快速求得前缀和和修改某一元素值

    - 本人的LeetCode账号:魔术师的徒弟,欢迎关注获取每日一题题解,快来一起刷题呀~ 本人Gitee账号:路由器,欢迎关注获取博客内容源码.   树状数组和其他的高级数据结构不同,它非常的好写,同 ...

  7. BZOJ3295 [Cqoi2011]动态逆序对 分治 树状数组

    原文链接http://www.cnblogs.com/zhouzhendong/p/8678185.html 题目传送门 - BZOJ3295 题意 对于序列$A$,它的逆序对数定义为满足$i< ...

  8. 洛谷 - P2163 [SHOI2007]园丁的烦恼(不带修二维数点-树状数组/主席树)

    题目链接:点击查看 题目大意:二维平面坐标系中给出 nnn 个坐标点,然后是 mmm 次询问,每次询问需要回答一个闭合矩阵中有多少个点 题目分析:想挂树套树来着,但是复杂度有点大.本题不带修且可以离线 ...

  9. 数据结构一【树状数组】普通、二维、离线树状数组的(单点修改,单点查询,区间修改,区间查询)模板及应用例题总结

    文章目录 树状数组 lowbit 线段树与树状数组 单点修改 区间查询 区间修改 区间求和 二维树状数组 离线树状数组 例题 POJ:stars MooFest [SDOI2009]HH的项链 Tur ...

  10. HDU4417 Super Mario(离线树状数组或者主席树+二分)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

最新文章

  1. 节后综合征疗愈神器,这个开源项目帮你10分钟上手AI算法开发!
  2. Nature:功能微生物组研究典范—采用甘露糖苷选择性抑制尿路致病性大肠杆菌...
  3. 一大清早,我就被编辑赶出了办公室……
  4. 罗斯蒙特1056ph电极_ROSEMOUNT 罗斯蒙特 PH电极 0396R-10-2(0396R-10-2)
  5. [云炬创业管理笔记]第三章打造优秀创业团队讨论1
  6. 安装好机器学习环境的虚拟机_虚拟环境之外的数据科学是弄乱机器的好方法
  7. 全国二级计算机理论知识,2021年度全国计算机等级考试二级MSOffice常考知识点基础知识部分.doc...
  8. 微信公开课讲师王泓渊:小游戏开放能力
  9. 请君入瓮: 火眼自称遭某 APT 国家黑客组织攻击
  10. Flink 源码: 从 KeyGroup 到 Rescale
  11. 用html制作四行四列的表格,HTML表格
  12. python实现虚拟键盘
  13. Arduino开发实例-433M无线模块数据发送与接收
  14. 联想ERP项目实施案例分析(9):工作方法总结
  15. 关于间皮瘤mesothelioma的相关信息
  16. 【敏捷】主要角色和分工
  17. 微分几何的24-33节笔记暂记(第一基本形式,第二基本形式)
  18. 基于微软平台IIS/ASP.NET开发的大型网站有哪些?
  19. VisualSVN server 备份恢复
  20. 短线黑马选股绝技 一

热门文章

  1. ans函数python_#12 Python函数
  2. 评分卡模型开发(一)--用户数据缺失值处理
  3. mysql case then效率快_详解Mysql case then使用
  4. linux 自动补全快捷键,day4 Linux下的快捷键和基本命令
  5. mysql 组复制和传统复制_2017年12月聚合文章--MySQL 传统复制中常见故障处理和结构优化案例分析 | 码友网...
  6. 【知识索引】【C++入门】
  7. Windows核心编程_修改开机密码
  8. 再学Android之屏幕适配
  9. LeetCode 655. Print Binary Tree (C++)
  10. for each,for in,for of三者区别