zoukankan      html  css  js  c++  java
  • BZOJ 3224 普通平衡树 treap or vector

        很明显这是一道treap的题,但看了黄学长的博客后,也让我大开了眼界,没想到vector也能用那么短的编码量把这道题AC,着实令我敬佩。这也提醒了我 STL 的重要性。 的确, 对于C++ 选手来说,如果能灵活地使用 STL, 的确受益匪浅(虽然速度可能比其他的慢一点,但正确性和编程复杂度都比其他的好,如果时间复杂度允许,在紧张的编程时间内,STL或许会是不错的选择)。 

    这是STL(vector)的代码, 用到了 insert, lowerr_bound, erase 等函数, 加油。(1700多毫秒)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<set>
     6 #include<vector>
     7 #include<algorithm>
     8 #define inf 1000000000
     9 using namespace std;
    10 
    11 inline int read()
    12 {
    13     int x=0,f=1;char ch=getchar();
    14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    16     return x*f;
    17 }
    18 int n;
    19 vector<int> a;
    20 
    21 void insert(int x)
    22 {
    23     a.insert(upper_bound(a.begin(),a.end(),x),x);
    24     return;
    25 }
    26 
    27 void del(int x)
    28 {
    29     a.erase(lower_bound(a.begin(),a.end(),x));
    30     return;
    31 }
    32 int find(int x)
    33 {
    34     return lower_bound(a.begin(),a.end(),x)-a.begin()+1;
    35 }
    36 int main()
    37 {
    38     n=read();
    39     a.reserve(200000);
    40     int f,x;
    41     for(int i=1;i<=n;i++)
    42     {
    43         f=read();x=read();
    44         switch(f)
    45         {
    46         case 1:insert(x);break;
    47         case 2:del(x);break;
    48         case 3:printf("%d
    ",find(x));break;
    49         case 4:printf("%d
    ",a[x-1]);break;
    50         case 5:printf("%d
    ",*--lower_bound(a.begin(),a.end(),x));break;
    51         case 6:printf("%d
    ",*upper_bound(a.begin(),a.end(),x));break;
    52         }
    53     }
    54     return 0;
    55 }

    接下来肯定是treap 的代码了,orz 黄学长。从他那里,着实学了不少好东西。(300多毫秒,比上面快多了吧!这个时间差距主要是因为查如何删除造成的)。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstdlib>
      4 #define rep(i,j,k) for(int i = j; i <= k; i++)
      5 using namespace std;
      6 
      7 struct node{
      8 int c[2], w, s, v, rnd;
      9 } tr[100005];
     10 
     11 int n, ans, root, size;
     12 
     13 int read()
     14 {
     15     int s = 0, t = 1; char c= getchar();
     16     while( !isdigit(c) ){
     17         if( c == '-' ) t = -1; c = getchar();
     18     }
     19     while( isdigit(c) ){
     20         s = s * 10 + c - '0'; c = getchar();
     21     }
     22     return s * t;
     23 }
     24 
     25 void update(int k)
     26 {
     27     tr[k].s = tr[tr[k].c[0]].s + tr[tr[k].c[1]].s + tr[k].w;
     28 }
     29 
     30 void rorate(int&k,int d)
     31 {
     32     int y = tr[k].c[d^1]; tr[k].c[d^1] = tr[y].c[d];
     33     tr[y].c[d] = k; update(k), update(y), k = y;
     34 }
     35 
     36 void insert(int&k,int x)
     37 {
     38     if( k == 0 ){
     39         ++size; k = size; tr[k].c[0] = tr[k].c[1] = 0, tr[k].s = tr[k].w = 1, tr[k].v = x, tr[k].rnd = rand();
     40         return;
     41     }
     42     tr[k].s++;
     43     if( x == tr[k].v ) tr[k].w++;
     44     else if( x < tr[k].v) {
     45         insert(tr[k].c[0],x); 
     46         if( tr[tr[k].c[0]].rnd > tr[k].rnd )rorate(k,1);
     47     }
     48     else {
     49         insert(tr[k].c[1],x);
     50         if( tr[tr[k].c[1]].rnd > tr[k].rnd ) rorate(k,0);
     51     }
     52 }
     53 
     54 void delt(int&k,int x)
     55 {
     56     if( !k ) return;
     57     if( tr[k].v == x ){
     58         if( tr[k].w > 1 ) {
     59             tr[k].w--, tr[k].s--;  return;
     60         }
     61         else {
     62             if( tr[k].c[0] * tr[k].c[1] == 0 ) k = tr[k].c[0] + tr[k].c[1];
     63             else {
     64                 if( tr[tr[k].c[0]].rnd > tr[tr[k].c[1]].rnd ) {
     65                     rorate(k,1); delt(k,x);
     66                 }
     67                 else {
     68                     rorate(k,0); delt(k,x);
     69                 }
     70             }
     71         }
     72     }
     73     else {
     74         tr[k].s--;
     75         if( x < tr[k].v ) delt(tr[k].c[0],x);
     76         else delt(tr[k].c[1],x);
     77     }
     78 }
     79 
     80 int query_rank(int k,int x)
     81 {
     82     if( !k ) return 0;
     83     if( tr[k].v == x ) return tr[tr[k].c[0]].s + 1;
     84     else if( tr[k].v < x ) return tr[tr[k].c[0]].s + tr[k].w + query_rank(tr[k].c[1],x);
     85     else return query_rank(tr[k].c[0],x);
     86 }
     87 
     88 int query_num(int k,int num)
     89 {
     90     if( !k ) return 0;
     91     if( tr[tr[k].c[0]].s >= num ) return query_num(tr[k].c[0],num);
     92     else if( tr[tr[k].c[0]].s + tr[k].w < num ) return query_num(tr[k].c[1],num-tr[tr[k].c[0]].s - tr[k].w);
     93     else return tr[k].v;
     94 }
     95 
     96 void query_pre(int k,int x)
     97 {
     98     if( !k ) return;
     99     if( tr[k].v < x ){
    100         ans = k, query_pre(tr[k].c[1],x);
    101     }
    102     else  query_pre(tr[k].c[0],x);
    103 }
    104 
    105 void query_suc(int k,int x)
    106 {
    107     if( !k ) return;
    108     if( tr[k].v > x ){
    109         ans = k, query_suc(tr[k].c[0],x);
    110     }
    111     else  query_suc(tr[k].c[1],x);
    112 }
    113 
    114 int main()
    115 {
    116     scanf("%d",&n);
    117     int opt,x;
    118     for(int i=1;i<=n;i++)
    119     {
    120         scanf("%d%d",&opt,&x);
    121         switch(opt)
    122         {
    123         case 1:insert(root,x);break;
    124         case 2:delt(root,x);break;
    125         case 3:printf("%d
    ",query_rank(root,x));break;
    126         case 4:printf("%d
    ",query_num(root,x));break;
    127         case 5:ans=0;query_pre(root,x);printf("%d
    ",tr[ans].v);break;
    128         case 6:ans=0;query_suc(root,x);printf("%d
    ",tr[ans].v);break;
    129         }
    130     }
    131     return 0;
    132 }

    3224: Tyvj 1728 普通平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 5783  Solved: 2381
    [Submit][Status][Discuss]

    Description

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    Input

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

    Output

    对于操作3,4,5,6每行输出一个数,表示对应答案

    Sample Input

    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598

    Sample Output

    106465
    84185
    492737

    HINT

    1.n的数据范围:n<=100000

    2.每个数的数据范围:[-1e7,1e7]

    Source

  • 相关阅读:
    UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)
    UVA 1572 Self-Assembly(拓扑排序)
    最大流当前弧优化Dinic分层模板
    POJ 3683.Priest John's Busiest Day 2-SAT
    n的m划分 整数拆分问题
    表达式计算
    大白书中无向图的点双联通分量(BCC)模板的分析与理解
    Codeforces 766D. Mahmoud and a Dictionary 并查集 二元敌对关系 点拆分
    树状数组入门
    Tire树入门专题
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5093211.html
Copyright © 2011-2022 走看看