• Bzoj3196 Tyvj 1730 二逼平衡树


    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 3350  Solved: 1324

    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

    树套树

    线段树套平衡树(treap)

    外层线段树维护区间,内层treap维护该区间内的数值

    代码超长看着就累

    Bzoj过了,Tyvj上最后两个点过不去,迷

    标题仿佛在嘲笑那些光写平衡树的人,又仿佛在嘲讽我这种模板题调一下午的人……

    小发现:对拍的时候,要是每次错得不一样,基本上可以确定是旋转错了/结点删错了

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<ctime>
      7 using namespace std;
      8 const int mxn=50010;
      9 int read(){
     10     int x=0,f=1;char ch=getchar();
     11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
     13     return x*f;
     14 }
     15 int n,m,root[mxn<<2];
     16 struct node{
     17     int l,r;int w,rand;int cnt,size;
     18 }t[mxn*60];
     19 int cnt=0;
     20 void pushup(int rt){
     21     t[rt].size=t[t[rt].l].size+t[t[rt].r].size+t[rt].cnt;return;
     22 }
     23 void lturn(int &rt){
     24     int tmp=t[rt].r;
     25     t[rt].r=t[tmp].l; t[tmp].l=rt;
     26     t[tmp].size=t[rt].size;
     27     pushup(rt);    rt=tmp;
     28     return;
     29 }
     30 void rturn(int &rt){
     31     int tmp=t[rt].l;
     32     t[rt].l=t[tmp].r; t[tmp].r=rt;
     33     t[tmp].size=t[rt].size;
     34     pushup(rt);    rt=tmp;
     35     return;
     36 }
     37 void insert(int w,int &rt){
     38     if(!rt){
     39         rt=++cnt;
     40         t[rt].l=t[rt].r=0;
     41         t[rt].size=t[rt].cnt=1;
     42         t[rt].rand=rand();
     43         t[rt].w=w;
     44         return;
     45     }
     46     t[rt].size++;
     47     if(t[rt].w==w){t[rt].cnt++;return;}
     48     if(w<t[rt].w){insert(w,t[rt].l);if(t[t[rt].l].rand>t[rt].rand)rturn(rt);}
     49     else {insert(w,t[rt].r);if(t[t[rt].r].rand>t[rt].rand)lturn(rt);}
     50     return;
     51 }
     52 void Del(int w,int &rt){
     53     if(t[rt].w==w){
     54         if(t[rt].cnt>1){t[rt].cnt--;t[rt].size--;return;}
     55         if(t[rt].l*t[rt].r==0)rt=t[rt].l+t[rt].r;
     56         else 
     57             if(t[t[rt].l].rand>t[t[rt].r].rand)
     58             {rturn(rt);Del(w,rt);}
     59             else{lturn(rt);Del(w,rt);}//开始写成Del(w,t[rt].l) WA了 
     60         return;
     61     }
     62     else if(w>t[rt].w)Del(w,t[rt].r);
     63         else Del(w,t[rt].l);
     64     t[rt].size--;
     65     return;
     66 }
     67 //
     68 void Build(int p,int v,int l,int r,int rt){
     69     insert(v,root[rt]);
     70     if(l==r)return;
     71     int mid=(l+r)>>1;
     72     if(p<=mid)Build(p,v,l,mid,rt<<1);
     73     else Build(p,v,mid+1,r,rt<<1|1);
     74     return;
     75 }
     76 void update(int p,int last,int v,int l,int r,int rt){//改变某位置的值 
     77 //    printf("p:%d last:%d v:%d l:%d r:%d rt:%d
    ",p,last,v,l,r,rt);
     78     Del(last,root[rt]);//删除旧值 
     79     insert(v,root[rt]);//添加新值 
     80     if(l==r)return;
     81     int mid=(l+r)>>1;
     82     if(p<=mid)update(p,last,v,l,mid,rt<<1);
     83     else update(p,last,v,mid+1,r,rt<<1|1);
     84     return;
     85 }
     86 //
     87 int rank1(int w,int rt){
     88     if(!rt)return 0;
     89     if(w==t[rt].w){return t[t[rt].l].size;}
     90     if(w<t[rt].w)return rank1(w,t[rt].l);
     91     else return t[t[rt].l].size+t[rt].cnt+rank1(w,t[rt].r);
     92 }
     93 int Qrk(int L,int R,int num,int l,int r,int rt){//查找num的排名 
     94     if(L<=l && r<=R)return rank1(num,root[rt]);
     95     int mid=(l+r)>>1;
     96     int res=0;
     97     if(L<=mid)res+=Qrk(L,R,num,l,mid,rt<<1);
     98     if(R>mid)res+=Qrk(L,R,num,mid+1,r,rt<<1|1);
     99     return res;
    100 }
    101 int Qnum(int L,int R,int k){//查找排名为k的数 
    102     int l=0,r=1e9,ans=0;
    103     while(l<=r){//二分答案 
    104         int mid=(l+r)>>1;
    105         int res=Qrk(L,R,mid,1,n,1)+1;
    106         if(res<=k){l=mid+1;ans=mid;}
    107         else r=mid-1;
    108     }
    109     return ans;
    110 }
    111 int res=0;//存储前驱/后继答案
    112 void Pre(int w,int rt){
    113     if(!rt)return;
    114     if(t[rt].w<w){res=max(res,t[rt].w);Pre(w,t[rt].r);}
    115     else Pre(w,t[rt].l);
    116     return;
    117 }
    118 void Sub(int w,int rt){
    119     if(!rt)return;
    120     if(t[rt].w>w){res=min(res,t[rt].w);Sub(w,t[rt].l);}
    121     else Sub(w,t[rt].r);
    122     return;
    123 }
    124 void Qpre(int L,int R,int num,int l,int r,int rt){
    125     if(L<=l && r<=R){Pre(num,root[rt]);return;}
    126     int mid=(l+r)>>1;
    127     if(L<=mid)Qpre(L,R,num,l,mid,rt<<1);
    128     if(R>mid)Qpre(L,R,num,mid+1,r,rt<<1|1);
    129     return;
    130 }
    131 void Qsub(int L,int R,int num,int l,int r,int rt){
    132 //    printf("!
    ");
    133     if(L<=l && r<=R){Sub(num,root[rt]);return;}
    134     int mid=(l+r)>>1;
    135     if(L<=mid)Qsub(L,R,num,l,mid,rt<<1);
    136     if(R>mid)Qsub(L,R,num,mid+1,r,rt<<1|1);
    137     return;
    138 }
    139 int a[mxn];
    140 int main(){
    141     int i,j,x,y,w;
    142     n=read();m=read();
    143     srand(time(0));
    144     for(i=1;i<=n;i++){a[i]=read();Build(i,a[i],1,n,1);}
    145     int op;
    146     while(m--){
    147         op=read();
    148         switch(op){
    149             case 1:{
    150                 x=read();y=read();w=read();
    151                 printf("%d
    ",Qrk(x,y,w,1,n,1)+1);
    152                 break;
    153             }
    154             case 2:{
    155                 x=read();y=read();w=read();
    156                 printf("%d
    ",Qnum(x,y,w));
    157                 break;
    158             }
    159             case 3:{
    160                 x=read();y=read();
    161                 update(x,a[x],y,1,n,1);
    162                 a[x]=y;
    163                 break;
    164             }
    165             case 4:{
    166                 x=read();y=read();w=read();
    167                 res=-1e9;
    168                 Qpre(x,y,w,1,n,1);
    169                 printf("%d
    ",res);
    170                 break;
    171             }
    172             case 5:{
    173                 x=read();y=read();w=read();
    174                 res=1e9;
    175                 Qsub(x,y,w,1,n,1);
    176                 printf("%d
    ",res);
    177                 break;
    178             }
    179         }
    180     }
    181     return 0;
    182 }
  • 相关阅读:
    Objective-C 生成器模式 -- 简单实用和说明
    Objective-C 桥接模式 -- 简单实用和说明
    Objective-C 工厂模式(下) -- 抽象工厂模式
    Objective-C 工厂模式(上) -- 简单工厂模式
    Linux篇---Vi的使用
    【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用
    【Spark篇】---SparkStreaming算子操作transform和updateStateByKey
    【Spark篇】---SparkStream初始与应用
    【Spark篇】---SparkSQL on Hive的配置和使用
    【Spark篇】---Spark中Shuffle机制,SparkShuffle和SortShuffle
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6359017.html
Copyright © 2020-2023  润新知