zoukankan      html  css  js  c++  java
  • bzoj3196 二逼平衡树 树套树(线段树套Treap)

    Tyvj 1730 二逼平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 4697  Solved: 1798
    [Submit][Status][Discuss]

    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
    1.查询k在区间内的排名
    2.查询区间内排名为k的值
    3.修改某一位值上的数值
    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Input

    第一行两个数 n,m 表示长度为n的有序序列和m个操作
    第二行有n个数,表示有序序列
    下面有m行,opt表示操作标号
    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    HINT

    1.n和m的数据范围:n,m<=50000


    2.序列中每个数的数据范围:[0,1e8]


    3.虽然原题没有,但事实上5操作的k可能为负数

    Source

    题解:

      这道题目的第二个操作没什么办法,唉,记得当时有log n 的算法的,现在只有log^2n的算法,o( ̄ヘ ̄o#)

      线段树套平衡树吧,这里选的是Treap

      1 #include<cstring>
      2 #include<cmath>
      3 #include<algorithm>
      4 #include<iostream>
      5 #include<cstdio>
      6 
      7 #define N 200007
      8 #define M 4000007
      9 #define inf 2000000007
     10 using namespace std;
     11 inline int read()
     12 {
     13     int x=0,f=1;char ch=getchar();
     14     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
     15     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 
     19 int n,m,ans,sz;
     20 int ls[M],rs[M],rnd[M],val[M],siz[M],ct[M];
     21 int root[N],a[N];
     22 
     23 inline int rand()
     24 {
     25     static int seed=2333;
     26     return seed=(int)((((seed^998244353)+19260817ll)*19890604ll)%1000000007);
     27 }
     28 void update(int p){siz[p]=siz[ls[p]]+siz[rs[p]]+ct[p];}
     29 void rturn(int &p){int t=ls[p];ls[p]=rs[t];rs[t]=p;siz[t]=siz[p];update(p);p=t;}
     30 void lturn(int &p){int t=rs[p];rs[p]=ls[t];ls[t]=p;siz[t]=siz[p];update(p);p=t;}
     31 void ins(int &p,int z)
     32 {
     33     if (!p)
     34     {
     35         p=++sz;
     36         siz[p]=ct[p]=1;
     37         val[p]=z;
     38         rnd[p]=rand();
     39         return;
     40     }
     41     siz[p]++;
     42     if (z==val[p])ct[p]++;
     43     else if (z<val[p])
     44          {
     45               ins(ls[p],z);
     46              if (rnd[ls[p]]<rnd[p]) rturn(p);
     47          }
     48     else 
     49          {
     50               ins(rs[p],z);
     51              if (rnd[rs[p]]<rnd[p]) lturn(p); 
     52          }
     53 }
     54 void del(int &p,int x)
     55 {
     56     if (p==0) return;
     57     if (val[p]==x)
     58     {
     59         if (ct[p]>1) ct[p]--,siz[p]--;//如果有多个直接减一即可。
     60         else
     61         {
     62             if (ls[p]==0||rs[p]==0) p=ls[p]+rs[p];//单节点或者空的话直接儿子移上来或者删去即可。
     63             else if (rnd[ls[p]]<rnd[rs[p]]) rturn(p),del(p,x);
     64             else lturn(p),del(p,x); 
     65         }
     66     }
     67     else if (x>val[p]) siz[p]--,del(rs[p],x);
     68     else siz[p]--,del(ls[p],x);
     69 }
     70 void build(int p,int l,int r,int x,int z)
     71 {
     72     ins(root[p],z);
     73     if (l==r) return;
     74     int mid=(l+r)>>1;
     75     if(x<=mid)build(p<<1,l,mid,x,z);
     76     else build(p<<1|1,mid+1,r,x,z);
     77 }
     78 void get_rank_sec(int p,int z)
     79 {
     80     if (!p) return;//没有不需要。
     81     if (z==val[p]) ans+=siz[ls[p]];
     82     else if (z<val[p]) get_rank_sec(ls[p],z);
     83     else
     84     {
     85         ans+=siz[ls[p]]+ct[p];
     86         get_rank_sec(rs[p],z); 
     87     }
     88 }
     89 void get_rank_fir(int p,int l,int r,int x,int y,int z)
     90 {
     91     if (l==x&&r==y)
     92     {
     93         get_rank_sec(root[p],z);
     94         return;
     95     }
     96     int mid=(l+r)>>1;
     97     if (y<=mid) get_rank_fir(p<<1,l,mid,x,y,z);
     98     else if (x>mid) get_rank_fir(p<<1|1,mid+1,r,x,y,z);
     99     else get_rank_fir(p<<1,l,mid,x,mid,z),get_rank_fir(p<<1|1,mid+1,r,mid+1,y,z);
    100 }
    101 void mid_to_find_index(int x,int y,int z)
    102 {
    103     int l=0,r=inf,res;
    104     while(l<=r)
    105     {
    106         int mid=(l+r)>>1;
    107         ans=1;get_rank_fir(1,1,n,x,y,mid);
    108         if(ans<=z){l=mid+1;res=mid;}
    109         else r=mid-1;
    110         }
    111     printf("%d
    ",res);
    112 }
    113 void modify(int p,int l,int r,int x,int yl,int xz)
    114 {
    115     del(root[p],yl);
    116     ins(root[p],xz);
    117     if (l==r) return;
    118     int mid=(l+r)>>1;
    119     if (x<=mid)modify(p<<1,l,mid,x,yl,xz);
    120     else modify(p<<1|1,mid+1,r,x,yl,xz);
    121 }
    122 void find_before_sec(int p,int z)
    123 {
    124     if (!p) return;
    125     if (val[p]<z)
    126     {
    127         ans=max(ans,val[p]);
    128         find_before_sec(rs[p],z);
    129     }
    130     else find_before_sec(ls[p],z);
    131 }
    132 void find_before_fir(int p,int l,int r,int x,int y,int z)
    133 {
    134     if (l==x&&r==y)
    135     {
    136         find_before_sec(root[p],z);
    137         return;
    138     }
    139     int mid=(l+r)>>1;
    140     if (y<=mid) find_before_fir(p<<1,l,mid,x,y,z);
    141     else if (x>mid) find_before_fir(p<<1|1,mid+1,r,x,y,z);
    142     else find_before_fir(p<<1,l,mid,x,mid,z),find_before_fir(p<<1|1,mid+1,r,mid+1,y,z);
    143 }
    144 void find_after_sec(int p,int z)
    145 {
    146     if(!p)return;
    147     if(val[p]>z)
    148     {
    149         ans=min(val[p],ans);
    150         find_after_sec(ls[p],z);
    151     }
    152     else find_after_sec(rs[p],z);
    153 }
    154 void find_after_fir(int p,int l,int r,int x,int y,int z)
    155 {
    156     if (l==x&&r==y)
    157     {
    158         find_after_sec(root[p],z);
    159         return;
    160     }
    161     int mid=(l+r)>>1;
    162     if (y<=mid) find_after_fir(p<<1,l,mid,x,y,z);
    163     else if (x>mid) find_after_fir(p<<1|1,mid+1,r,x,y,z);
    164     else find_after_fir(p<<1,l,mid,x,mid,z),find_after_fir(p<<1|1,mid+1,r,mid+1,y,z);
    165 }
    166 int main()
    167 {
    168     n=read(),m=read();
    169     for (int i=1;i<=n;i++)
    170         a[i]=read(),build(1,1,n,i,a[i]);
    171     while(m--)
    172     {
    173         int flag=read(),x,y,k;
    174         switch(flag)
    175         {
    176             case 1:x=read(),y=read(),k=read(),ans=1,get_rank_fir(1,1,n,x,y,k),printf("%d
    ",ans);break;
    177             case 2:x=read(),y=read(),k=read(),mid_to_find_index(x,y,k);break;
    178             case 3:x=read(),y=read(),modify(1,1,n,x,a[x],y),a[x]=y;break;
    179             case 4:x=read(),y=read(),k=read(),ans=0,find_before_fir(1,1,n,x,y,k),printf("%d
    ",ans);break;
    180             case 5:x=read(),y=read(),k=read(),ans=inf,find_after_fir(1,1,n,x,y,k),printf("%d
    ",ans);break;
    181         }
    182     }
    183 }
  • 相关阅读:
    叶落归根(hometown)
    设置(settings)
    文明距离(civil)
    计算机基础知识
    gojs插件使用教程
    编程语言分类
    dp优化简单总结
    Splay入门题目 [HNOI2002]营业额统计
    hdu3415:最大k子段和,单调队列
    hdu5072(鞍山regional problem C):容斥,同色三角形模型
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8142738.html
Copyright © 2011-2022 走看看