【模板】可持久化数组(可持久化线段树/平衡树)
题目背景
UPDATE : 最后一个点时间空间已经放大
标题即题意
有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集)
题目描述
如题,你需要维护这样的一个长度为 N N N 的数组,支持如下几种操作
在某个历史版本上修改某一个位置上的值
访问某个历史版本上的某一位置的值
此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)
输入输出格式
输入格式:
输入的第一行包含两个正整数 N,M N, M N,M, 分别表示数组的长度和操作的个数。
第二行包含N N N个整数,依次为初始状态下数组各位的值(依次为 ai a_i ai,1≤i≤N 1 \leq i \leq N 1≤i≤N)。
接下来M M M行每行包含3或4个整数,代表两种操作之一(i i i为基于的历史版本号):
对于操作1,格式为vi 1 loci valuei v_i \ 1 \ {loc}_i \ {value}_i vi 1 loci valuei,即为在版本vi v_i vi的基础上,将 aloci a_{{loc}_i} aloci 修改为 valuei {value}_i valuei
对于操作2,格式为vi 2 loci v_i \ 2 \ {loc}_i vi 2 loci,即访问版本vi v_i vi中的 aloci a_{{loc}_i} aloci的值,生成一样版本的对象应为vi
输出格式:
输出包含若干行,依次为每个操作2的结果。
输入输出样例
5 10 59 46 14 87 41 0 2 1 0 1 1 14 0 1 1 57 0 1 1 88 4 2 4 0 2 5 0 2 4 4 2 1 2 2 2 1 1 5 91
59 87 41 87 88 46
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<time.h>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 2000005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
#define mclr(x,a) memset((x),a,sizeof(x))
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;inline int rd() {int x = 0;char c = getchar();bool f = false;while (!isdigit(c)) {if (c == '-') f = true;c = getchar();}while (isdigit(c)) {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f ? -x : x;
}ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; }/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {if (!b) {x = 1; y = 0; return a;}ans = exgcd(b, a%b, x, y);ll t = x; x = y; y = t - a / b * y;return ans;
}
*/int n, m;
int rt[maxn];
int a[1000004];
struct node {int val[maxn * 10], ls[maxn * 10], rs[maxn * 10];int tot = 0;inline void build(int &o, int l, int r) {o = ++tot;if (l == r) {val[o] = a[l]; return;}int mid = (l + r) >> 1;build(ls[o], l, mid); build(rs[o], mid + 1, r);}inline void upd(int &o, int pre, int l, int r, int Val,int x) {o = ++tot; val[o] = val[pre]; ls[o] = ls[pre]; rs[o] = rs[pre];if (l == r) {val[o] = Val; return;}int mid = (l + r) >> 1;if (x <= mid)upd(ls[o], ls[pre], l, mid, Val, x);else upd(rs[o], rs[pre], mid + 1, r, Val, x);}inline int query(int o, int l, int r, int x) {if (l == r)return val[o];int mid = (l + r) >> 1;if (x <= mid)return query(ls[o], l, mid, x);else return query(rs[o], mid + 1, r, x);}
}seg;int main()
{// ios::sync_with_stdio(0);n = rd(); m = rd();for (int i = 1; i <= n; i++)a[i] = rd();seg.build(rt[0], 1, n);for (int i = 1; i <= m; i++) {int V = rd(), opt = rd(), loc = rd();if (opt == 1) {int vu = rd();seg.upd(rt[i], rt[V], 1, n, vu, loc);}else {int ans = seg.query(rt[V], 1, n, loc);printf("%d\n", ans); rt[i] = rt[V];}}return 0;
}
转载于:https://www.cnblogs.com/zxyqzy/p/10363986.html
【模板】可持久化数组(可持久化线段树/平衡树)相关推荐
- P3919 【模板】可持久化数组(可持久化线段树/平衡树)
题目描述 如题,你需要维护这样的一个长度为 N 的数组,支持如下几种操作 在某个历史版本上修改某一个位置上的值 访问某个历史版本上的某一位置的值 此外,每进行一次操作(对于操作2,即为生成一个完全一 ...
- P3919 【模板】可持久化数组(可持久化线段树/平衡树)(入门第一题)
学习博客:http://www.cnblogs.com/flashhu/p/8297581.html 题目链接:https://www.luogu.org/problemnew/show/P3919 ...
- LGOJ P3919【模板】可持久化数组(可持久化线段树/平衡树)
代码 //可持久化线段树 #include <cstdio> using namespace std;struct node {node *Lnode,*Rnode;int val;voi ...
- Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】
题目分析: 这道题我是乱搞的,因为他说$01$串是随机的. 那么我们可以猜测能够让LCP变大的地方很少.求出后缀数组之后可能让LCP变大的地方就等价于从大到小往height里动态加点同时维护这个点左右 ...
- 【BZOJ2441】【中山市选2011】小W的问题(树状数组+权值线段树)
传送门 由于一个www不好统计,我们考虑拆成222个vvv来统计,也就是"312"和"213"这样的 把答案统计在"2"处,两边相乘就是答案 ...
- 【后缀数组】【线段树】codeforces102028H Can You Solve the Harder Problem?
H. Can You Solve the Harder Problem? time limit per test6.0 s memory limit per test1024 MB inputstan ...
- HDU 4417 Super Mario(线段树||树状数组+离线操作 之线段树篇)
Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...
- HDU 6194 string string string 后缀数组 + RMQ(线段树)
传送门:HDU6194 题意:问给定字符串中有多少种出现k次的子串. 思路:首先想到后缀数组经典问题,求出现不少于k次的子串的最大长度,类似的这题肯定就是在height数组上搞事情啦. 将height ...
- 数据结构 【树状数组】【线段树】【珂朵莉树】
一.区间合并 1.AcWing245你能回答这些问题吗 分析: 线段树.维护四个变量,即可实现区间合并. mx 区间最大连续子段和 mx_l 以区间左端点为左界的最大连续字段和 mx_r 以区间左端点 ...
最新文章
- 建设网站套用模板优化难吗?
- Spring AOP源码分析(七)ProxyFactoryBean介绍
- OpenAI“单手解魔方”被公开质疑,Gary Marcus称七大问题涉嫌误导
- 华为麒麟1020处理器曝光:性能提升50%,5nm制程!Mate 40有望成为首发机型
- Halcon 多个点拟合圆
- CCF201412-3 集合竞价(100分)
- linux佳入门教程,命令行基础工具的更佳替代品
- GEM TSU Interface Details and IEEE 1588 Support
- Little Elephant and Magic Square
- svn 服务器端密码修改,svn服务器端设置密码
- Android架构师绩效考核表,半年绩效考核总结(7.9)
- 分享《Essential Linux Device Drivers》中文版高清电子版
- 使用 Piral 创建微前端
- 电子商务数据分析的认识
- 零基础如何快速学习Java?Java基础入门秘诀
- 2021-07-30 es6 -第4章和String复习
- 【PAT甲级】1131 Subway Map
- Java Web中涉及的编解码
- 记录一个CMake编译报错undefined reference to vtable问题的解决
- 暗影精灵8 安装ubuntu 问题汇总
热门文章
- vue.js反编译_基于electron-vue开发的微信小程序反编译客户端
- 显示计算机硬盘驱动器更改,笔记本硬盘驱动器的字母怎么修改?笔记本修改硬盘驱动器字母的方法...
- echarts 动态改变数据_Echarts的使用
- java红黑树_JAVA学习-红黑树详解
- shell 脚本 进行sqlite3初始化
- JS 新浪下拉菜单+jQuery
- FPGA之道(20)FPGA设计的上板调试与项目总结
- 【 FPGA 】设置伪路径
- MapReduce 中文版论文(转载)
- Node.js使用NodeMailer发送邮件