zoukankan      html  css  js  c++  java
  • 【模板】可持久化数组(可持久化线段树/平衡树)

    题目背景

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

    标题即题意

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

    题目描述

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

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

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

    此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)

    输入输出格式

    输入格式:

    输入的第一行包含两个正整数 N,M N, M N,M, 分别表示数组的长度和操作的个数。

    第二行包含N N N个整数,依次为初始状态下数组各位的值(依次为 ai a_i ai1≤i≤N 1 leq i leq N 1iN)。

    接下来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
    ", ans); rt[i] = rt[V];
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    centos7安装KVM
    keepalived高可用
    Jenkins-Pipeline 流水线发布部署项目
    centos7部署jenkins
    版本控制gitlab
    c语言寻找3000以内亲密数对
    c语言寻找1000以内的完全数
    c语言分解因式
    c语言判断给定日期是当年的第几天
    c语言计算程序运行时间
  • 原文地址:https://www.cnblogs.com/zxyqzy/p/10363986.html
Copyright © 2011-2022 走看看