zoukankan      html  css  js  c++  java
  • bzoj3196: Tyvj 1730 二逼平衡树

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #define maxn 50005
      7 #define maxk 2000005
      8 #define inf 100000000
      9 using namespace std;
     10 
     11 int n,m,tot,sum,Ans,root[maxn<<2],val[maxk],times[maxk],size[maxk],fa[maxk],son[maxk][2],a[maxn];
     12 struct Tsegment{
     13     void clear(){
     14         tot=0,memset(val,0,sizeof(val));
     15         memset(root,0,sizeof(0));
     16         memset(son,0,sizeof(son));
     17         memset(fa,0,sizeof(fa));
     18         memset(times,0,sizeof(times));
     19         memset(size,0,sizeof(size));
     20     }
     21     int which(int x){return son[fa[x]][1]==x;}
     22     void update(int x){
     23         size[x]=size[son[x][0]]+size[son[x][1]]+times[x];
     24     }
     25     void rotata(int x){
     26         int y=fa[x],d=which(x),dd=which(y);
     27         if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y];
     28         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
     29         fa[y]=x,son[x][d^1]=y,update(y);
     30     }
     31     void splay(int x,int goal,int op){
     32         while (fa[x]!=goal){
     33             if (fa[fa[x]]==goal) rotata(x);
     34             else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
     35             else rotata(x),rotata(x);
     36         }
     37         update(x); if (goal==0) root[op]=x;
     38     }
     39     void insert(int k,int x){
     40         int y=root[k]; bool bo;
     41         if (y==0){
     42             root[k]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=son[tot][0]=son[tot][1]=0;
     43             return;
     44         }
     45         for (;;){
     46             bo=0;
     47             if (val[y]==x) times[y]++,size[y]++,bo=1,splay(y,0,k);
     48             else if (x<val[y]){
     49                 if (!son[y][0]) son[y][0]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=y,bo=1,splay(tot,0,k);
     50                 else y=son[y][0];
     51             }else{
     52                 if (!son[y][1]) son[y][1]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=y,bo=1,splay(tot,0,k);
     53                 else y=son[y][1];
     54             }
     55             if (bo==1) break;
     56         }
     57     }
     58     void query(int k,int x){
     59         int y=root[k]; if (y==0) return;
     60         for (;;){
     61             if (y==0) break;
     62             if (val[y]==x){
     63                 sum+=size[son[y][0]];
     64                 break;
     65             }else if (val[y]<x){
     66                 sum+=(size[son[y][0]]+times[y]);
     67                 y=son[y][1];
     68             }else y=son[y][0];
     69         }
     70     }
     71     int prep(int k,int x){
     72         splay(x,0,k);
     73         int y=son[x][0];
     74         while (son[y][1]) y=son[y][1];
     75         return y;
     76     }
     77     void DLT(int k,int x){
     78         int y=prep(k,x),z;
     79         if (y==0){
     80             splay(x,0,k);
     81             z=son[x][1];
     82             fa[z]=0,son[x][0]=son[x][1]=0,fa[x]=0,root[k]=z,times[x]=size[x]=0;
     83             splay(z,0,k);
     84         }else{
     85             splay(y,0,k),splay(x,y,k);
     86             z=son[x][1];
     87             fa[z]=y,son[y][1]=z,fa[x]=son[x][0]=son[x][1]=size[x]=times[x]=0;
     88             update(y);
     89         }
     90     }
     91     void dlt(int k,int x){
     92         int y=root[k]; if (y==0) return; bool bo;
     93         for (;;){
     94             bo=0;
     95             if (val[y]==x){
     96                 if (times[y]>1) times[y]--,size[y]--,bo=1,splay(y,0,k);
     97                 else{
     98                     times[y]--,size[y]--,bo=1,DLT(k,y);
     99                 }
    100             }else if (x<val[y]) y=son[y][0];
    101             else y=son[y][1];
    102             if (bo==1) break;
    103         }
    104     }
    105     void query4(int k,int x){
    106         int y=root[k]; if (y==0) return;
    107         for (;;){
    108             if (y==0) break;
    109             if (val[y]<x) Ans=max(Ans,val[y]),y=son[y][1];
    110             else y=son[y][0];
    111         }
    112     }
    113     void query5(int k,int x){
    114         int y=root[k]; if (y==0) return;
    115         for (;;){
    116             if (y==0) break;
    117             if (x<val[y]) Ans=min(Ans,val[y]),y=son[y][0];
    118             else y=son[y][1];
    119         }
    120     }
    121 }Splay;
    122 struct date{
    123     void insert(int k,int l,int r,int x){
    124         Splay.insert(k,a[x]);
    125         if (l==r) return;
    126         int mid=(l+r)>>1;
    127         if (x<=mid) insert(k*2,l,mid,x);
    128         else insert(k*2+1,mid+1,r,x);
    129     }
    130     void query(int k,int l,int r,int x,int y,int z){
    131         if (l>=x&&r<=y){
    132             Splay.query(k,z);
    133             return;
    134         }int mid=(l+r)>>1;
    135         if (x<=mid) query(k*2,l,mid,x,y,z);
    136         if (y>mid) query(k*2+1,mid+1,r,x,y,z);
    137     }
    138     int check(int x,int y,int z){
    139         sum=0,query(1,1,n,x,y,z);
    140         return sum;
    141     }
    142     void dlt(int k,int l,int r,int x,int y){
    143         Splay.dlt(k,y);
    144         if (l==r) return;
    145         int mid=(l+r)>>1;
    146         if (x<=mid) dlt(k*2,l,mid,x,y);
    147         else dlt(k*2+1,mid+1,r,x,y);
    148     }
    149     void query4(int k,int l,int r,int x,int y,int z){
    150         if (l>=x&&r<=y){
    151             Splay.query4(k,z);
    152             return;
    153         }int mid=(l+r)>>1;
    154         if (x<=mid) query4(k*2,l,mid,x,y,z);
    155         if (y>mid) query4(k*2+1,mid+1,r,x,y,z);
    156     }
    157     void query5(int k,int l,int r,int x,int y,int z){
    158         if (l>=x&&r<=y){
    159             Splay.query5(k,z);
    160             return;
    161         }int mid=(l+r)>>1;
    162         if (x<=mid) query5(k*2,l,mid,x,y,z);
    163         if (y>mid) query5(k*2+1,mid+1,r,x,y,z);
    164     }
    165 }Tree;
    166 struct note{
    167     void query1(int x,int y,int z){
    168         sum=0,Tree.query(1,1,n,x,y,z);
    169         printf("%d
    ",++sum);
    170     }
    171     void query2(int x,int y,int z){
    172         int low=0,high=inf,mid,ans=0;
    173         while (low<=high){
    174             mid=(low+high)/2;
    175             if (Tree.check(x,y,mid)+1<=z) ans=mid,low=mid+1;
    176             else high=mid-1;
    177         }
    178         printf("%d
    ",ans);
    179     }
    180     void query3(int x,int y){
    181         Tree.dlt(1,1,n,x,a[x]);
    182         a[x]=y,Tree.insert(1,1,n,x);
    183     }
    184     void query4(int x,int y,int z){
    185         Ans=0;
    186         Tree.query4(1,1,n,x,y,z);
    187         printf("%d
    ",Ans);
    188     }
    189     void query5(int x,int y,int z){
    190         Ans=inf;
    191         Tree.query5(1,1,n,x,y,z);
    192         printf("%d
    ",Ans);
    193     }
    194 }Task;
    195 
    196 int main(){
    197     int oppo,u,v,w;
    198     scanf("%d%d",&n,&m);
    199     Splay.clear();
    200     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    201     for (int i=1;i<=n;i++) Tree.insert(1,1,n,i);
    202     while (m--){
    203          scanf("%d%d%d",&oppo,&u,&v);
    204         if (oppo==1) scanf("%d",&w),Task.query1(u,v,w);
    205         else if (oppo==2) scanf("%d",&w),Task.query2(u,v,w);
    206         else if (oppo==3) Task.query3(u,v);
    207          else if (oppo==4) scanf("%d",&w),Task.query4(u,v,w);
    208         else scanf("%d",&w),Task.query5(u,v,w);
    209     }
    210     return 0;
    211 }
    View Code

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3196

    题目大意:

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

    序列长度为n,操作个数为m,n<=5*10^4,m<=5*10^4;

    做法:对于区间最大值或区间最小值我们可以用线段树,对于整个序列第k小,求排名,求前驱,求后继,我们可以用splay,-->那么对于区间求排名,求第k小,求前驱,求后继,我们可以用树套树,线段树套splay,线段树维护区间位置,对于线段树的每个节点,我们维护一棵splay,维护这段区间中的权值。每加入一个点,需要增开logn的空间,故空间复杂度为(n+m)logn,操作1,3,4,5的时间复杂度均为log^2 n,操作2的时间复杂度为log^3 n;可以过此题。

    对于操作1:我们在线段树上找相应的区间,在其splay上询问有多少个节点权值<它,最后把sum++,即为答案,脑补;

    对于操作2:我们考虑二分答案,即转化为了操作1,若该答案的排名<=k,ans=mid,l=mid+1,否则r=mid-1,输出ans即可;

    对于操作3:线段树中,将所有包含该位置的点原来的权值删去,并将新权值加入;

    对于操作4:在每棵splay上查找即可(splay具有二分性质);

    对于操作5:与操作4相似;

    注意:线段树记录相应splay的根,每次将某个节点旋到所在splay树上的根是,记得更新线段树记录的根,以防出错。

    具体细节见代码。

    树套树,线段树套splay。

  • 相关阅读:
    Maximum execution time of 30 seconds exceeded解决错误方法
    php 获取随机数的几个方式
    php header utf8 插入header("Content-type: text/html; charset=utf-8");
    php mysqli query 查询数据库后读取内容的方法
    win7 xampp 验证码,session出不来的问题
    apache 中 ServerAlias让多个域名绑定到同一空间
    最近很火的一条成长公式,看看你属于那一条!
    用crontab执行shell把top命令按日期追加到文件
    php CI 实战教程第一季百度经验杂志
    php 截取字符串第一个字符,截取掉字符串最后一个字符的方法
  • 原文地址:https://www.cnblogs.com/OYzx/p/5538270.html
Copyright © 2011-2022 走看看