题目背景

UPDATE : 最后一个点时间空间已经放大

标题即题意

有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集)

题目描述

如题,你需要维护这样的一个长度为 N N N 的数组,支持如下几种操作

  1. 在某个历史版本上修改某一个位置上的值

  2. 访问某个历史版本上的某一位置的值

此外,每进行一次操作(对于操作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. 对于操作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. 对于操作2,格式为vi 2 loci v_i \ 2 \ {loc}_i vi​ 2 loci​,即访问版本vi v_i vi​中的 aloci a_{{loc}_i} aloci​​的值,生成一样版本的对象应为vi

输出格式:

输出包含若干行,依次为每个操作2的结果。

输入输出样例

输入样例#1: 复制

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

输出样例#1: 复制

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

【模板】可持久化数组(可持久化线段树/平衡树)相关推荐

  1. P3919 【模板】可持久化数组(可持久化线段树/平衡树)

    题目描述 如题,你需要维护这样的一个长度为 N  的数组,支持如下几种操作 在某个历史版本上修改某一个位置上的值 访问某个历史版本上的某一位置的值 此外,每进行一次操作(对于操作2,即为生成一个完全一 ...

  2. P3919 【模板】可持久化数组(可持久化线段树/平衡树)(入门第一题)

    学习博客:http://www.cnblogs.com/flashhu/p/8297581.html 题目链接:https://www.luogu.org/problemnew/show/P3919 ...

  3. LGOJ P3919【模板】可持久化数组(可持久化线段树/平衡树)

    代码 //可持久化线段树 #include <cstdio> using namespace std;struct node {node *Lnode,*Rnode;int val;voi ...

  4. Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】

    题目分析: 这道题我是乱搞的,因为他说$01$串是随机的. 那么我们可以猜测能够让LCP变大的地方很少.求出后缀数组之后可能让LCP变大的地方就等价于从大到小往height里动态加点同时维护这个点左右 ...

  5. 【BZOJ2441】【中山市选2011】小W的问题(树状数组+权值线段树)

    传送门 由于一个www不好统计,我们考虑拆成222个vvv来统计,也就是"312"和"213"这样的 把答案统计在"2"处,两边相乘就是答案 ...

  6. 【后缀数组】【线段树】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 ...

  7. HDU 4417 Super Mario(线段树||树状数组+离线操作 之线段树篇)

    Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...

  8. HDU 6194 string string string 后缀数组 + RMQ(线段树)

    传送门:HDU6194 题意:问给定字符串中有多少种出现k次的子串. 思路:首先想到后缀数组经典问题,求出现不少于k次的子串的最大长度,类似的这题肯定就是在height数组上搞事情啦. 将height ...

  9. 数据结构 【树状数组】【线段树】【珂朵莉树】

    一.区间合并 1.AcWing245你能回答这些问题吗 分析: 线段树.维护四个变量,即可实现区间合并. mx 区间最大连续子段和 mx_l 以区间左端点为左界的最大连续字段和 mx_r 以区间左端点 ...

最新文章

  1. 建设网站套用模板优化难吗?
  2. Spring AOP源码分析(七)ProxyFactoryBean介绍
  3. OpenAI“单手解魔方”被公开质疑,Gary Marcus称七大问题涉嫌误导
  4. 华为麒麟1020处理器曝光:性能提升50%,5nm制程!Mate 40有望成为首发机型
  5. Halcon 多个点拟合圆
  6. CCF201412-3 集合竞价(100分)
  7. linux佳入门教程,命令行基础工具的更佳替代品
  8. GEM TSU Interface Details and IEEE 1588 Support
  9. Little Elephant and Magic Square
  10. svn 服务器端密码修改,svn服务器端设置密码
  11. Android架构师绩效考核表,半年绩效考核总结(7.9)
  12. 分享《Essential Linux Device Drivers》中文版高清电子版
  13. 使用 Piral 创建微前端
  14. 电子商务数据分析的认识
  15. 零基础如何快速学习Java?Java基础入门秘诀
  16. 2021-07-30 es6 -第4章和String复习
  17. 【PAT甲级】1131 Subway Map
  18. Java Web中涉及的编解码
  19. 记录一个CMake编译报错undefined reference to vtable问题的解决
  20. 暗影精灵8 安装ubuntu 问题汇总

热门文章

  1. vue.js反编译_基于electron-vue开发的微信小程序反编译客户端
  2. 显示计算机硬盘驱动器更改,笔记本硬盘驱动器的字母怎么修改?笔记本修改硬盘驱动器字母的方法...
  3. echarts 动态改变数据_Echarts的使用
  4. java红黑树_JAVA学习-红黑树详解
  5. shell 脚本 进行sqlite3初始化
  6. JS 新浪下拉菜单+jQuery
  7. FPGA之道(20)FPGA设计的上板调试与项目总结
  8. 【 FPGA 】设置伪路径
  9. MapReduce 中文版论文(转载)
  10. Node.js使用NodeMailer发送邮件