zoukankan      html  css  js  c++  java
  • BZOJ 3196 二逼平衡树

    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可能为负数
    写了不很久,但是交上去一直都是TLE,发现splay被卡了。最后采用随机提根法,卡过去了。
    一道树套树的裸题(很明显线段树套平衡树)。
      1 #include<iostream>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 using namespace std;
      6 
      7 #define inf (1<<29)
      8 #define lim (100000000)
      9 #define maxn (50010)
     10 #define maxm (3000010)
     11 int n,m,root[maxn*4],seq[maxn];
     12 struct SPLAY
     13 {
     14     queue <int> team; int cnt,ch[maxm][2],fa[maxm],key[maxm],t[maxm],size[maxm];
     15 
     16     inline int newnode()
     17     {
     18         int ret;
     19         if (!team.empty()) ret = team.front(),team.pop();
     20         else ret = ++cnt;
     21         fa[ret] = ch[ret][0] = ch[ret][1] = t[ret] = 0;
     22         return ret;
     23     }
     24     
     25     inline void updata(int now) { size[now] = size[ch[now][0]] + size[ch[now][1]] + t[now]; }
     26 
     27     inline void rotate(int x)
     28     {
     29         int y = fa[x],z = fa[y],l = ch[y][1] == x,r = l^1;
     30         if (z) ch[z][ch[z][1] == y] = x; fa[x] = z;
     31         if (ch[x][r]) fa[ch[x][r]] = y; ch[y][l] = ch[x][r];
     32         ch[x][r] = y; fa[y] = x;
     33         updata(y); updata(x);
     34     }
     35     
     36     inline void splay(int x,int rt)
     37     {
     38         while (fa[x])
     39         {
     40             int y = fa[x],z = fa[y];
     41             if (z)
     42             {
     43                 if ((ch[y][0] == x)^(ch[z][0] == y)) rotate(x);
     44                 else rotate(y);
     45             }
     46             rotate(x);
     47         }
     48         root[rt] = x;
     49     }
     50     
     51     inline void init(int rt)
     52     {
     53         int p = newnode(),q = newnode();
     54         root[rt] = p; ch[p][1] = q; fa[q] = p;
     55         t[p]++; key[p] = -inf; t[q]++; key[q] = inf;
     56         updata(q); updata(p);
     57     }
     58 
     59     inline int find(int w,int rt,int sign)
     60     {
     61         int now = root[rt],ret;
     62         while (now)
     63         {
     64             if (!sign)
     65             {
     66                 if (key[now] == w) return now;
     67                 now = ch[now][key[now]<w];
     68             }
     69             else if (sign == 1)
     70             {
     71                 if (key[now] < w) ret = now,now = ch[now][1];
     72                 else now = ch[now][0];
     73             }
     74             else if (sign == 2)
     75             {
     76                 if (key[now] > w) ret = now,now = ch[now][0];
     77                 else now = ch[now][1];
     78             }
     79             else
     80             {
     81                 if (key[now] >= w) ret = now,now = ch[now][0];
     82                 else now = ch[now][1];
     83             }
     84         }
     85         return ret;
     86     }
     87 
     88     inline void erase(int w,int rt)
     89     {
     90         int p = find(w,rt,0);
     91         while (ch[p][0]||ch[p][1])
     92         {
     93             if (ch[p][0])
     94             {
     95                 if (root[rt] == p) root[rt] = ch[p][0];
     96                 rotate(ch[p][0]);
     97             }
     98             else
     99             {
    100                 if (root[rt] == p) root[rt] = ch[p][1];
    101                 rotate(ch[p][1]);
    102             }
    103         }
    104         int now = p;
    105         if (!--t[now]) ch[fa[now]][key[fa[now]] < key[now]] = 0,team.push(now);
    106         else updata(now);
    107         while (now = fa[now],now) updata(now);
    108     }
    109 
    110     inline void insert(int w,int rt)
    111     {
    112         int now = root[rt],pre = 0;
    113         while (now)
    114         {
    115             if (key[now] == w) { ++t[now]; break; }
    116             pre = now; now = ch[now][w > key[now]];
    117         }
    118         if (!now)
    119             now = newnode(),fa[now] = pre,ch[pre][w > key[pre]] = now,key[now] = w,++t[now];
    120         for (pre = now;pre;pre = fa[pre]) updata(pre);
    121         if (w & 1) splay(now,rt);
    122     }
    123 
    124     inline int rank(int w,int rt)
    125     {
    126         int p = find(w,rt,3); splay(p,rt);
    127         return size[ch[p][0]];
    128     }
    129 }tree;
    130 
    131 inline void build(int l,int r,int now)
    132 {
    133     tree.init(now);
    134     for (int i = l;i <= r;++i) tree.insert(seq[i],now);
    135     if (l == r) return;
    136     int mid = (l + r) >> 1;
    137     build(l,mid,now<<1); build(mid+1,r,now<<1|1);
    138 }
    139 
    140 inline int rank(int l,int r,int ql,int qr,int now,int w)
    141 {
    142     if (ql <= l && qr >= r) return tree.rank(w,now)-1;
    143     int mid = (l + r) >> 1;
    144     if (qr <= mid) return rank(l,mid,ql,qr,now<<1,w);
    145     else if (ql > mid) return rank(mid+1,r,ql,qr,now<<1|1,w);
    146     else return rank(l,mid,ql,mid,now<<1,w)+rank(mid+1,r,ql,qr,now<<1|1,w);
    147 }
    148 
    149 inline void change(int l,int r,int now,int pos,int w)
    150 {
    151     tree.erase(seq[pos],now); tree.insert(w,now);
    152     if (l == r) return;
    153     int mid = (l + r) >> 1;
    154     if (pos <= mid) change(l,mid,now<<1,pos,w);
    155     else change(mid+1,r,now<<1|1,pos,w);
    156 }
    157 
    158 inline int ask(int l,int r,int ql,int qr,int now,int w,int sign)
    159 {
    160     if (ql <= l && qr >= r) return tree.key[tree.find(w,now,sign)];
    161     int mid = (l + r)>>1;
    162     if (qr <= mid) return ask(l,mid,ql,qr,now<<1,w,sign);
    163     else if (ql > mid) return ask(mid+1,r,ql,qr,now<<1|1,w,sign);
    164     else
    165     {
    166         if (sign == 1) return max(ask(l,mid,ql,mid,now<<1,w,sign),ask(mid+1,r,mid+1,qr,now<<1|1,w,sign));
    167         else return min(ask(l,mid,ql,mid,now<<1,w,sign),ask(mid+1,r,mid+1,qr,now<<1|1,w,sign));
    168     }
    169 }
    170 
    171 int main()
    172 {
    173     freopen("3196.in","r",stdin);
    174     freopen("3196.out","w",stdout);
    175     scanf("%d %d",&n,&m);
    176     for (int i = 1;i <= n;++i) scanf("%d",seq+i);
    177     build(1,n,1);
    178     while (m--)
    179     {
    180         int opt; scanf("%d",&opt);
    181         if (opt == 1)
    182         {
    183             int l,r,w; scanf("%d %d %d",&l,&r,&w);
    184             printf("%d
    ",rank(1,n,l,r,1,w)+1);
    185         }
    186         else if (opt == 2)
    187         {
    188             int l,r,k; scanf("%d %d %d",&l,&r,&k);
    189             int ll = 0,rr = lim;
    190             while (ll <= rr)
    191             {
    192                 int mid = (ll + rr) >> 1;
    193                 if (rank(1,n,l,r,1,mid)+1>k) rr = mid - 1;
    194                 else ll = mid + 1;
    195             }
    196             printf("%d
    ",rr);
    197         }
    198         else if (opt == 3)
    199         { 
    200             int pos,w; scanf("%d %d",&pos,&w);
    201             change(1,n,1,pos,w); seq[pos] = w;
    202         }
    203         else
    204         {
    205             int l,r,w; scanf("%d %d %d",&l,&r,&w);
    206             printf("%d
    ",ask(1,n,l,r,1,w,opt-3));
    207         }
    208     }
    209     fclose(stdin); fclose(stdout);
    210     return 0;
    211 }
    View Code
  • 相关阅读:
    使用XStream解析xml
    分享功能
    上拉加载 下拉刷新
    点击button倒计时
    正则表达式验证手机号码
    第三方登陆
    test
    横向滑动菜单HorizontalScrollView
    slidingmenu侧滑侧单
    2017/4/25 afternoon
  • 原文地址:https://www.cnblogs.com/mmlz/p/4294474.html
Copyright © 2011-2022 走看看