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的值
    输出格式:

    输出包含若干行,依次为每个操作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

    说明

    数据规模:

    对于30%的数据:1≤N,M≤103 1 leq N, M leq {10}^3 1N,M103

    对于50%的数据:1≤N,M≤104 1 leq N, M leq {10}^4 1N,M104

    对于70%的数据:1≤N,M≤105 1 leq N, M leq {10}^5 1N,M105

    对于100%的数据:1≤N,M≤106,1≤loci≤N,0≤vi<i,−109≤ai,valuei≤109 1 leq N, M leq {10}^6, 1 leq {loc}_i leq N, 0 leq v_i < i, -{10}^9 leq a_i, {value}_i leq {10}^91N,M106,1lociN,0vi<i,109ai,valuei109

    经测试,正常常数的可持久化数组可以通过,请各位放心

    数据略微凶残,请注意常数不要过大

    另,此题I/O量较大,如果实在TLE请注意I/O优化

    样例说明:

    一共11个版本,编号从0-10,依次为:

    • 0 : 59 46 14 87 41

    • 1 : 59 46 14 87 41

    • 2 : 14 46 14 87 41

    • 3 : 57 46 14 87 41

    • 4 : 88 46 14 87 41

    • 5 : 88 46 14 87 41

    • 6 : 59 46 14 87 41

    • 7 : 59 46 14 87 41

    • 8 : 88 46 14 87 41

    • 9 : 14 46 14 87 41

    • 10 : 59 46 14 87 91

    思路

    其实就是写个可持久化线段树就行了;

    会了可持久化数组,就可以进行可持久化并查集的操作了QuQ

    代码实现

     1 #include<cstdio>
     2 const int maxn=1e6+10;
     3 int n,m;
     4 int rt[maxn],ts;
     5 int t[maxn<<4],ls[maxn<<4],rs[maxn<<4];
     6 void build(int&k,int l,int r){
     7     k=++ts;
     8     if(l==r){
     9         scanf("%d",&t[k]);
    10         return;
    11     }
    12     int mid=l+r>>1;
    13     build(ls[k],l,mid);
    14     build(rs[k],mid+1,r);
    15 }
    16 void change(int q,int&p,int l,int r,int x){
    17     p=++ts;
    18     if(l==r){
    19         scanf("%d",&t[p]);
    20         return;
    21     }
    22     int mid=l+r>>1;
    23     if(x<=mid) change(ls[q],ls[p],l,mid,x),rs[p]=rs[q];
    24     else change(rs[q],rs[p],mid+1,r,x),ls[p]=ls[q];
    25 }
    26 int search(int p,int l,int r,int x){
    27     if(l==r) return t[p];
    28     int mid=l+r>>1;
    29     if(x<=mid) return search(ls[p],l,mid,x);
    30     else return search(rs[p],mid+1,r,x);
    31 }
    32 int main(){
    33     scanf("%d%d",&n,&m);
    34     build(rt[0],1,n);
    35     int id,opt,l;
    36     for(int i=1;i<=m;i++){
    37         scanf("%d%d%d",&id,&opt,&l);
    38         if(opt==1) change(rt[id],rt[i],1,n,l);
    39         else printf("%d
    ",search(rt[id],1,n,l)),rt[i]=rt[id];
    40     }
    41     return 0;
    42 }
  • 相关阅读:
    BZOJ 1069 最大土地面积
    BZOJ 1059 矩阵游戏
    BZOJ 3570 动物园
    Luogu 3934 Nephren Ruq Insania
    Luogu 3233 [HNOI2014]世界树
    CF613D Kingdom and its Cities
    Luogu 4001 [BJOI2006]狼抓兔子
    Luogu 2824 [HEOI2016/TJOI2016]排序
    POJ 3463 Sightseeing
    Luogu 2495 [SDOI2011]消耗战
  • 原文地址:https://www.cnblogs.com/J-william/p/8136005.html
Copyright © 2011-2022 走看看