1 条题解

  • 0
    @ 2026-4-5 1:47:17
    #include <bits/stdc++.h>
    using namespace std;
    
    #define lc(p) tr[p].ls
    #define rc(p) tr[p].rs
    
    const int N = 3e5 + 10;
    struct node {
        int ls, rs, val, siz, rnd;
    } tr[N * 20];
    
    int trlen, T, rt[N];
    
    void pushup(int p) {
        tr[p].siz = tr[lc(p)].siz + tr[rc(p)].siz + 1;
    }
    
    int newd(node no) {
        tr[++trlen] = no;
        return trlen;
    }
    
    int newd(int v) {
        tr[++trlen] = {0, 0, v, 1, rand()};
        return trlen;
    }
    
    // 本题按树的大小 siz 划分,可持久化 split 需要在路径上复制节点
    void split(int p, int k, int &x, int &y) {
        if (p == 0) {
            x = y = 0;
            return;
        }
        if (tr[lc(p)].siz < k) {
            x = newd(tr[p]); // 复制当前节点
            split(rc(p), k - tr[lc(p)].siz - 1, rc(x), y);
            pushup(x);
        } else {
            y = newd(tr[p]); // 复制当前节点
            split(lc(p), k, x, lc(y));
            pushup(y);
        }
    }
    
    int merge(int x, int y) {
        if (!x || !y) return x + y;
        if (tr[x].rnd < tr[y].rnd) {
            rc(x) = merge(rc(x), y);
            pushup(x);
            return x;
        } else {
            lc(y) = merge(x, lc(y));
            pushup(y);
            return y;
        }
    }
    
    int getval(int p, int k) {
        if (tr[lc(p)].siz + 1 == k) return tr[p].val;
        if (k <= tr[lc(p)].siz) return getval(lc(p), k);
        else return getval(rc(p), k - tr[lc(p)].siz - 1);
    }
    
    int main() {
        int n;
        scanf("%d", &n);
        rt[0] = 0;
        T = trlen = 0;
        
        int x, y, z, t, k, v, op;
        while (n--) {
            scanf("%d", &op);
            if (op == 1) {
                scanf("%d%d%d", &t, &k, &v);
                rt[++T] = rt[t]; // 继承历史版本
                split(rt[T], k - 1, x, y);
                rt[T] = merge(merge(x, newd(v)), y);
            }
            if (op == 2) {
                scanf("%d%d", &t, &k);
                rt[++T] = rt[t]; // 继承历史版本
                // 修正后的删除逻辑:
                split(rt[T], k, x, y);    // x 包含前 k 个元素,y 包含第 k+1 个及以后的元素
                split(x, k - 1, x, z);    // x 包含前 k-1 个元素,z 为第 k 个元素(将被丢弃)
                rt[T] = merge(x, y);      // 合并前 k-1 个和剩余部分,实现删除
            }
            if (op == 3) {
                scanf("%d%d", &t, &k);
                printf("%d\n", getval(rt[t], k));
            }
        }
        return 0;
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    #define lc(p) tr[p].ls
    #define rc(p) tr[p].rs
    const int N=3e5+10;
    struct node{int ls,rs,val,siz,rnd;}tr[N*20];int trlen,T,rt[N];
    void pushup(int p){tr[p].siz=tr[lc(p)].siz+tr[rc(p)].siz+1;}
    int newd(node no){tr[++trlen]=no;               return trlen; }
    int newd(int   v){tr[++trlen]={0,0,v,1,rand()}; return trlen; }
    void split(int p,int k,int &x,int &y)//本题按树的大小siz划分 
    {
        if(p==0){x=y=0;return ;}
        if(tr[lc(p)].siz<k)
        {
            x=newd(tr[p]);
            split(rc(p),k-tr[lc(p)].siz-1,rc(x),y);
            pushup(x);
        }
        else 
        {
            y=newd(tr[p]);
            split(lc(p),k,x,lc(y));
            pushup(y);
        }
    }
    
    int merge(int x,int y)
    {
    	if(!x||!y) return x+y;
    	if(tr[x].rnd<tr[y].rnd)
    	{
    		rc(x)=merge(rc(x),y);
    		pushup(x);
    		return x;
    	}
    	else
    	{
    		lc(y)=merge(x,lc(y));
    		pushup(y);
    		return y;
    	}
    }
    int getval(int p,int k)
    {
    	if(tr[lc(p)].siz+1==k) return tr[p].val;
    	if(k<=tr[lc(p)].siz)   return getval(lc(p),k);
        else                   return getval(rc(p),k-tr[lc(p)].siz-1);
    }
    int main()
    {
        int n;scanf("%d",&n);
        rt[0]=0;T=trlen=0;
        int x,y,z,t,k,v,op;
        while(n--)
    	{
            scanf("%d",&op);
            if(op==1)
    		{
                scanf("%d%d%d",&t,&k,&v);rt[++T]=rt[t];
                split(rt[T],k-1,x,y);
                rt[T]=merge(merge(x,newd(v)),y);
            }
            if(op==2)
    		{
                scanf("%d%d",&t,&k);rt[++T]=rt[t];
                split(rt[T],k,x,y);
                split(x,k-1,x,z);
                rt[T]=merge(x,y);
            }
            if(op==3)
    		{
                scanf("%d%d",&t,&k);
                printf("%d\n",getval(rt[t],k));
            }
        }
        return 0;
    }
    
    • 1

    *【可持久化FHQ Treep】持久化序列

    信息

    ID
    523
    时间
    1500ms
    内存
    768MiB
    难度
    8
    标签
    (无)
    递交数
    260
    已通过
    35
    上传者