• PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树


    #44. 【HNSDFZ2016 #6】可持久化线段树

     统计

    题目描述

    现有一序列 AA。您需要写一棵可持久化线段树,以实现如下操作:

    • A v p x:对于版本v的序列,给 ApAp 增加 xx.
    • Q v l r:对于版本v的序列,询问 A[l,r]A[l,r] 的区间和。
    • C v:拷贝一份版本v的序列,编号为当前版本总数+1.

    版本号从 11 开始;版本 11 的序列,所有元素均为 00.

    格式

    输入格式

    第一行,两个正整数 n,mn,m,表示序列的长度和操作个数。

    接下来 mm 行,每行输入一个操作,格式如题目描述所述。

    保证任何输入的数都是正整数

    输出格式

    对于每一个Q操作,输出一行一个整数,表示对应的区间和。

    样例数据

    样例输入

    5 5
    A 1 2 3
    Q 1 1 4
    C 1
    A 2 3 2
    Q 2 1 4

    样例输出

    3
    5

    解释

    第一次操作后,版本1的序列为:0 3 0 0 0.

    第二次操作询问版本1A[1,4]A[1,4]区间和,答案为0+3+0+0=30+3+0+0=3.

    第三次操作将版本1的序列复制到版本2.

    第四次操作后,版本2的序列为:0 3 2 0 0.

    第五次操作询问版本2A[1,4]A[1,4]区间和,答案为0+3+2+0=50+3+2+0=5.

    数据规模与约定

    对于20%20%的数据,有n1000,m100n≤1000,m≤100.

    对于40%40%的数据,有n100000,m50000n≤100000,m≤50000.

    对于100%100%的数据,有n1000000,m1500000n≤1000000,m≤1500000.

    对于100%100%的数据,v,p,l,rv,p,l,r均合法;为了避免爆int,保证1x101≤x≤10.

    时间限制:1s1s

    空间限制:128MB

    #include<cstdio>
    using namespace std;
    int read(){
        register int x=0,f=1;
        register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f; 
    }
    const int N=1.5e6+10;
    const int s=(1<<20);
    struct node{int v,next;}e[N];
    struct data{
        int opt,ver,l,r;
    }o[N];int cnt=1,tot=0;
    int n,m,last[N],head[N],ans[N],t[s<<1];
    void add(int x,int y){
        e[++tot]=(node){y,head[x]};head[x]=tot;
    }
    void updata(int x,int p){
        for(x+=s;x;x>>=1) t[x]+=p;
    }
    void del(int x,int p){
        for(x+=s;x;x>>=1) t[x]-=p;
    }
    inline int query(int l,int r){
        int ret=0;
        for(l+=s-1,r+=s+1;l^r^1;l>>=1,r>>=1){
            if(!(l&1)) ret+=t[l^1];
            if(r&1) ret+=t[r^1];
        }
        return ret;
    }
    void dfs(int x){
        if(o[x].opt==1) updata(o[x].l,o[x].r);
        else if(o[x].opt==2) ans[x]=query(o[x].l,o[x].r);
        for(int i=head[x];i;i=e[i].next) dfs(e[i].v);
        if(o[x].opt==1) del(o[x].l,o[x].r);
    }
    int main(){
        n=read();m=read();char s[2];
        last[1]=0;
        for(int i=1;i<=m;i++){
            scanf("%s",s);o[i].ver=read();
            if(s[0]=='C') o[i].opt=0;
            else if(s[0]=='A') o[i].opt=1;
            else o[i].opt=2;
            if(o[i].opt){
                o[i].l=read();o[i].r=read();
                add(last[o[i].ver],i);
                last[o[i].ver]=i;
            }
            else{
                add(last[o[i].ver],i);
                last[++cnt]=i;
            }
            if(o[i].opt!=2) ans[i]=-1;
        }
        dfs(1);
        for(int i=1;i<=m;i++) if(ans[i]!=-1) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    ubuntu下7z文件的解压
    Ubuntu16 编译源码出错 unsupported reloc 43
    两个超级大整数的相加,相乘
    c++ abcd....等等字符所有不同的非重复组合排布
    C# Java 通用MD5加密
    artDialog-学习课程(三) 参数配置表
    artDialog-学习课程(二)-常用弹出框
    MySQL 查看数据库数据表空间大小
    MySQL Date 函数
    artDialog-学习课程(一)-下载与引用
  • 原文地址:https://www.cnblogs.com/shenben/p/6256302.html
Copyright © 2020-2023  润新知