zoukankan      html  css  js  c++  java
  • luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

    luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iomanip>
    #include<algorithm>
    #include<ctime>
    #include<queue>
    #include<stack>
    #define rg register
    #define il inline
    #define lst long long
    #define N 1000050
    using namespace std;
    
    int n,Q,cnt;
    int val[N];
    int root[N];
    struct TREE{
        int ls,rs,v;
    }ljl[N*25];
    
    il int read()
    {
        rg int s=0,m=1;rg char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')m=-1,ch=getchar();
        while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        return s*m;
    }
    
    il void build(rg int &now,rg int le,rg int ri)
    //现在所在的点(可往回传参),  左端点,   右端点
    {
        ljl[++cnt]=ljl[now];//新开一个点……
        now=cnt;//保证now指的是当点这个点,因为还要传回去赋值给“爸爸的左/右儿子”……具体看后面的递归build
        if(le==ri){ljl[now].v=val[le];return;}//如果到单点赋值就ojbk了(同线段树)
        rg int mid=(le+ri)>>1;
        build(ljl[now].ls,le,mid),build(ljl[now].rs,mid+1,ri);
        //建造左儿子和右儿子,本节点向他们的指针在递归函数往回传参时会赋值(一切都源于一个美丽的“ & ”)
    }
    
    void Modify(rg int &now,rg int le,rg int ri,rg int kk,rg int x)//很像build
    //现在所在的点(可往回传参),左端点,右端点,要修改的点编号,修改后的值
    {
        ljl[++cnt]=ljl[now];//又要开点了……
        now=cnt;//保证now指的是当点这个点,因为还要传回去赋值给“爸爸的左/右儿子”……具体看后面的递归Modify
        if(le==ri){ljl[now].v=x;return;}//照样赋值
        rg int mid=(le+ri)>>1;
        if(kk<=mid)Modify(ljl[now].ls,le,mid,kk,x);
        else Modify(ljl[now].rs,mid+1,ri,kk,x);
        //kk在mid左边,就建左孩子,否则建右孩子……需要模拟哦……
    }
    
    int Query(rg int now,rg int le,rg int ri,rg int kk)
    {
        if(le==ri)return ljl[now].v;
        rg int mid=(le+ri)>>1;
        if(kk<=mid)return Query(ljl[now].ls,le,mid,kk);
        else return Query(ljl[now].rs,mid+1,ri,kk);
    }
    
    int main()
    {
        n=read(),Q=read();
        for(rg int i=1;i<=n;++i)val[i]=read();
        build(root[0],1,n);//先按原来的值建一棵线段树在0号根上
        for(rg int i=1;i<=Q;++i)
        {
            rg int edi=read(),type=read();//历史版本edi,询问type
            if(type==1)
            {
                rg int kk=read(),x=read();//把kk号的val改成x
                root[i]=root[edi];//先把根连过来,再修改!
                Modify(root[i],1,n,kk,x);//从根开始,左,右端点,修改的编号,修改成的值
            }
            else
            {
                rg int kk=read();
                printf("%d
    ",Query(root[edi],1,n,kk));//当前节点(也就是edi时的根),左,右端点,询问第kk号的值
                root[i]=root[edi];//这个依题,还是弄过来吧……
            }
        }
        return 0;
    }
  • 相关阅读:
    camp待补
    ZOJ
    ZOJ
    ZOJ
    CodeForces
    CodeForces
    POJ 3278 Catch That Cow(简单BFS)
    POJ 2251 Dungeon Master(三维BFS)
    POJ 1218 THE DRUNK JAILER(类开灯问题,完全平方数)
    HDU 2053 Switch Game(开灯问题,完全平方数)
  • 原文地址:https://www.cnblogs.com/cjoierljl/p/9107523.html
Copyright © 2011-2022 走看看