zoukankan      html  css  js  c++  java
  • 洛谷P3835 【模板】可持久化平衡树

    题目背景

    本题为题目 普通平衡树 的可持久化加强版。

    数据已经经过强化

    感谢@Kelin 提供的一组hack数据

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):

    1. 插入x数

    2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)

    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

    4. 查询排名为x的数

    5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)

    6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)

    和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)

    每个版本的编号即为操作的序号(版本0即为初始状态,空树)

    输入输出格式

    输入格式:

    第一行包含一个正整数N,表示操作的总数。

    接下来每行包含三个整数,第 i 行记为 vi,opti,xi

    vi表示基于的过去版本号( 0vi<i ),opti 表示操作的序号( 1opt6 ), xi 表示参与操作的数值

    输出格式:

    每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案

    输入输出样例

    输入样例#1: 
    10
    0 1 9
    1 1 3
    1 1 10
    2 4 2
    3 3 9
    3 1 2
    6 4 1
    6 2 9
    8 6 3
    4 5 8
    输出样例#1: 
    9
    1
    2
    10
    3

    说明

    数据范围:

    对于28%的数据满足: 1n10

    对于44%的数据满足: 1n210^2

    对于60%的数据满足: 1n310^3

    对于84%的数据满足: 1n10^5

    对于92%的数据满足: 1n210^5

    对于100%的数据满足: 1n510^5 , 10^9xi10^9

    经实测,正常常数的可持久化平衡树均可通过,请各位放心

    样例说明:

    共10次操作,11个版本,各版本的状况依次是:

    1. [][]

    2. [9][9]

    3. [3, 9][3,9]

    4. [9, 10][9,10]

    5. [3, 9][3,9]

    6. [9, 10][9,10]

    7. [2, 9, 10][2,9,10]

    8. [2, 9, 10][2,9,10]

    9. [2, 10][2,10]

    10. [2, 10][2,10]

    11. [3, 9][3,9]

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 using namespace std;
      6 long long read()
      7 {
      8     long long x=0,f=1;
      9     char ch=getchar();
     10     while(ch>'9'||ch<'0')
     11     {
     12         if(ch=='-')
     13             f=-1;
     14         ch=getchar();
     15     }
     16     while(ch>='0'&&ch<='9')
     17     {
     18         x=x*10+ch-'0';
     19         ch=getchar();
     20     }
     21     return x*f;
     22 }
     23 const int maxn=5e5+5;
     24 struct node
     25 {
     26     int l,r,v,rd,sum;
     27 } e[maxn*50];
     28 int n,num,x,y,opt;
     29 int root[maxn];
     30 void update(int i)
     31 {
     32     if(!i)
     33         return ;
     34     e[i].sum=e[e[i].l].sum+e[e[i].r].sum+1;
     35 }
     36 int add(int x)
     37 {
     38     ++num;
     39     e[num].l=e[num].r=0;
     40     e[num].sum=1;
     41     e[num].v=x;
     42     e[num].rd=rand();
     43     return num;
     44 }
     45 int merge(int x,int y)
     46 {
     47     if(!x||!y)
     48         return x+y;
     49     if(e[x].rd>e[y].rd)
     50     {
     51         int p=++num;
     52         e[p]=e[x];
     53         e[p].r=merge(e[p].r,y);
     54         update(p);
     55         return p;
     56     }
     57     else
     58     {
     59         int p=++num;
     60         e[p]=e[y];
     61         e[p].l=merge(x,e[p].l);
     62         update(p);
     63         return p;
     64     }
     65 }
     66 void split(int now,int k,int &x,int &y)
     67 {
     68     if(now==0)
     69     {
     70         x=y=0;
     71         return ;
     72     }
     73     if(e[now].v<=k)
     74     {
     75         x=++num;
     76         e[x]=e[now];
     77         split(e[x].r,k,e[x].r,y);
     78         update(x);
     79     }
     80     else
     81     {
     82         y=++num;
     83         e[y]=e[now];
     84         split(e[y].l,k,x,e[y].l);
     85         update(y);
     86     }
     87 }
     88 void insert(int &root,int v)
     89 {
     90     int x=0,y=0,z=0;
     91     split(root,v-1,x,y);
     92     z=add(v);
     93     root=merge(merge(x,z),y);
     94 }
     95 void del(int &root,int v)
     96 {
     97     int x=0,y=0,z=0;
     98     split(root,v,x,z);
     99     split(x,v-1,x,y);
    100     y=merge(e[y].l,e[y].r);
    101     root=merge(merge(x,y),z);
    102 }
    103 int rank(int i,int k)
    104 {
    105     if(k==e[e[i].l].sum+1)
    106         return e[i].v;
    107     if(k<=e[e[i].l].sum)
    108         return rank(e[i].l,k);
    109     return rank(e[i].r,k-e[e[i].l].sum-1);
    110 }
    111 int query(int &root,int v)
    112 {
    113     int x,y;
    114     split(root,v-1,x,y);
    115     int ans=e[x].sum+1;
    116     root=merge(x,y);
    117     return ans;
    118 }
    119 int pre(int &root,int v)
    120 {
    121     int x,y,k;
    122     split(root,v-1,x,y);
    123     if(x==0)
    124         return -2147483647;
    125     k=e[x].sum;
    126     int ans=rank(x,k);
    127     root=merge(x,y);
    128     return ans;
    129 }
    130 int nex(int &root,int v)
    131 {
    132     int x,y,ans;
    133     split(root,v,x,y);
    134     if(y==0)
    135         return 2147483647;
    136     ans=rank(y,1);
    137     root=merge(x,y);
    138     return ans;
    139 }
    140 int main()
    141 {
    142     n=read();
    143     for(int i=1; i<=n; i++)
    144     {
    145         x=read(),opt=read(),y=read();
    146         root[i]=root[x];
    147         if(opt==1)
    148             insert(root[i],y);
    149         if(opt==2)
    150             del(root[i],y);
    151         if(opt==3)
    152             printf("%d
    ",query(root[i],y));
    153         if(opt==4)
    154             printf("%d
    ",rank(root[i],y));
    155         if(opt==5)
    156             printf("%d
    ",pre(root[i],y));
    157         if(opt==6)
    158             printf("%d
    ",nex(root[i],y));
    159     }
    160     return 0;
    161 }
    View Code
  • 相关阅读:
    批量修改mp3文件播放速度
    尝试了一下alsa录音播放的编程。
    最快速获取天气的方法
    乒乓Buffer
    GCC编译选项和环境变量
    Linux发行版本
    memcpy 和 memmove
    自动定位android ndk的路径
    记一下,安装和使用Ubuntu过程中遇到的问题
    Android API 和Android 版本对照
  • 原文地址:https://www.cnblogs.com/liweilin/p/10227133.html
Copyright © 2011-2022 走看看