zoukankan      html  css  js  c++  java
  • zoj 2112 块状链表 OR 线段树套treap 求动态第k大

    块链:块内排序方便二分,然后进行类似于冒泡排序的更新即可。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <cmath>
      6 using namespace std;
      7 
      8 const int INF = 1000000000;
      9 const int N = 50000;
     10 const int M = 400;
     11 int a[N];
     12 int b[M][M];
     13 int n, m, ps, num;
     14 
     15 void update( int pos, int val )
     16 {
     17     int cur = pos / ps;
     18     if ( cur < num - 1 )
     19     {
     20         int p = lower_bound( b[cur], b[cur] + ps, a[pos] ) - b[cur];
     21         if ( val > a[pos] )
     22         {
     23             while ( p + 1 < ps && b[cur][p + 1] < val ) 
     24             {
     25                 b[cur][p] = b[cur][p + 1];
     26                 p++;
     27             }
     28         }
     29         else
     30         {
     31             while ( p - 1 >= 0 && b[cur][p - 1] > val )
     32             {
     33                 b[cur][p] = b[cur][p - 1];
     34                 p--;
     35             }
     36         }
     37         b[cur][p] = val;
     38     }
     39     a[pos] = val;
     40 }
     41 
     42 int query( int l, int r, int k )
     43 {
     44     int cur = l / ps, ncur = r / ps;
     45     int lb = 0, ub = INF;
     46     while ( lb < ub )
     47     {
     48         int mid = ( lb + ub ) >> 1;
     49         int cnt = 0;
     50         if ( cur != ncur )
     51         {
     52             for ( int i = cur + 1; i <= ncur - 1; i++ )
     53             {
     54                 cnt += upper_bound( b[i], b[i] + ps, mid ) - b[i];
     55             }
     56             for ( int i = l; i < ( cur + 1 ) * ps; i++ )
     57             {
     58                 if ( a[i] <= mid ) cnt++;
     59             }
     60             for ( int i = ncur * ps; i <= r; i++ )
     61             {
     62                 if ( a[i] <= mid ) cnt++;
     63             }
     64         }
     65         else
     66         {
     67             for ( int i = l; i <= r; i++ )
     68             {
     69                 if ( a[i] <= mid ) cnt++;
     70             } 
     71         }
     72         if ( cnt >= k )
     73         {
     74             ub = mid;
     75         }
     76         else
     77         {
     78             lb = mid + 1;
     79         }
     80     }
     81     return ub;
     82 }
     83 
     84 int main ()
     85 {
     86     int t;
     87     scanf("%d", &t);
     88     while ( t-- )
     89     {
     90         scanf("%d%d", &n, &m);
     91         ps = 400;
     92         for ( int i = 0; i < n; i++ )
     93         {
     94             scanf("%d", a + i);
     95             b[i / ps][i % ps] = a[i];
     96         }
     97         num = ( n + ps - 1 ) / ps;
     98         for ( int i = 0; i < num - 1; i++ )
     99         {
    100             sort( b[i], b[i] + ps );
    101         }
    102         while ( m-- )
    103         {
    104             char op[2];
    105             int x, y, k;
    106             scanf("%s", op);
    107             if ( op[0] == 'Q' )
    108             {
    109                 scanf("%d%d%d", &x, &y, &k);
    110                 x--, y--;
    111                 printf("%d
    ", query( x, y, k ));
    112             }
    113             else
    114             {
    115                 scanf("%d%d", &x, &y);
    116                 x--;
    117                 update( x, y );
    118             }
    119         }
    120     }
    121     return 0;
    122 }

    线段树套treap:线段树上的每个结点维护一个treap,里面有该区间的元素,查询时二分答案。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 using namespace std;
      6 
      7 const int INF = 1000000000;
      8 const int N = 100001;
      9 int a[N];
     10 int n, m;
     11 
     12 struct Node 
     13 {
     14     Node * ch[2];
     15     int v, r, size, cnt;
     16     int cmp( int x )
     17     {
     18         if ( x == v ) return -1;
     19         return x < v ? 0 : 1;
     20     }    
     21     void maintain()
     22     {
     23         size = cnt;
     24         if ( ch[0] != NULL ) size += ch[0]->size;
     25         if ( ch[1] != NULL ) size += ch[1]->size;
     26     }
     27 };
     28 
     29 void rotate( Node * & o, int d )
     30 {
     31     Node * k = o->ch[d ^ 1];
     32     o->ch[d ^ 1] = k->ch[d];
     33     k->ch[d] = o;
     34     o->maintain();
     35     k->maintain();
     36     o = k;
     37 }
     38 
     39 int ran()
     40 {
     41     static int x = 1364684679;
     42     x += ( ( x << 2 ) | 1 );
     43     return x;
     44 }
     45 
     46 void insert( Node * & o, int x )
     47 {
     48     if ( o == NULL )
     49     {
     50         o = new Node();
     51         o->ch[0] = o->ch[1] = NULL;
     52         o->v = x;
     53         o->r = ran();
     54         o->size = o->cnt = 1;
     55     }
     56     else
     57     {
     58         int d = o->cmp(x);
     59         if ( d == -1 )
     60         {
     61             o->cnt++;
     62             o->size++;
     63         }
     64         else
     65         {
     66             insert( o->ch[d], x );
     67             if ( o->ch[d]->r > o->r )
     68             {
     69                 rotate( o, d ^ 1 );
     70             }
     71             else
     72             {
     73                 o->maintain();
     74             }
     75         }
     76     }
     77 }
     78 
     79 void remove( Node * & o, int x )
     80 {
     81     int d = o->cmp(x);
     82     if ( d == -1 )
     83     {
     84         if ( o->cnt > 1 )
     85         {
     86             o->cnt--;
     87             o->size--;
     88         }
     89         else
     90         {
     91             if ( o->ch[0] != NULL && o->ch[1] != NULL )
     92             {
     93                 int dd = ( o->ch[0]->r > o->ch[1]->r ? 1 : 0 );
     94                 rotate( o, dd );
     95                 remove( o->ch[dd], x );
     96             }
     97             else
     98             {
     99                 Node * u = o;
    100                 if ( o->ch[0] == NULL ) o = o->ch[1];
    101                 else o = o->ch[0];
    102                 delete u;
    103             }
    104             if ( o != NULL ) o->maintain();
    105         }
    106     }
    107     else
    108     {
    109         remove( o->ch[d], x );
    110         o->maintain();
    111     }
    112 }
    113 
    114 int ranker( Node * o, int x, int sum )
    115 {
    116     if ( o == NULL ) return sum;
    117     int d = o->cmp(x);
    118     if ( d == -1 )
    119     {
    120         return sum + ( o->ch[0] == NULL ? 0 : o->ch[0]->size ) + o->cnt;
    121     }
    122     else if ( d == 0 )    
    123     {
    124         return ranker( o->ch[0], x, sum );
    125     }
    126     else
    127     {
    128         int tmp = ( o->ch[0] == NULL ? 0 : o->ch[0]->size );
    129         return ranker( o->ch[1], x, sum + tmp + o->cnt );
    130     }
    131 }
    132 
    133 struct S
    134 {
    135     int l, r;
    136     Node * rt;
    137 } s[N << 2];
    138 
    139 Node * build_treap( int l, int r )
    140 {
    141     Node * o = NULL;
    142     for ( int i = l; i <= r; i++ )
    143     {
    144         insert( o, a[i] );
    145     }
    146     return o;
    147 }
    148 
    149 void build( int i, int l, int r )
    150 {
    151     s[i].l = l, s[i].r = r;
    152     s[i].rt = build_treap( l, r );
    153     if ( l == r ) return ;
    154     int mid = ( l + r ) >> 1;
    155     build( i << 1, l, mid );
    156     build( i << 1 | 1, mid + 1, r );
    157 }
    158 
    159 void update( int i, int pos, int val )
    160 {
    161     if ( s[i].l == pos && s[i].r == pos )
    162     {
    163         s[i].rt->v = val;
    164         return ;
    165     }
    166     remove( s[i].rt, a[pos] );
    167     insert( s[i].rt, val );
    168     int mid = ( s[i].l + s[i].r ) >> 1;
    169     if ( pos <= mid )
    170     {
    171         update( i << 1, pos, val );
    172     }
    173     else
    174     {
    175         update( i << 1 | 1, pos, val );
    176     }
    177 }
    178 
    179 int query( int i, int l, int r, int val )
    180 {
    181     if ( s[i].l == l && s[i].r == r )
    182     {
    183         return ranker( s[i].rt, val, 0 );
    184     }
    185     int mid = ( s[i].l + s[i].r ) >> 1;
    186     if ( r <= mid )
    187     {
    188         return query( i << 1, l, r, val );
    189     }
    190     else if ( l > mid )
    191     {
    192         return query( i << 1 | 1, l, r, val );
    193     }
    194     else
    195     {
    196         return query( i << 1, l, mid, val ) + query( i << 1 | 1, mid + 1, r, val );
    197     }
    198 }
    199 
    200 int kth( int l, int r, int k )
    201 {
    202     int lb = 1, ub = INF;
    203     while ( lb < ub )
    204     {
    205         int mid = ( lb + ub ) >> 1;
    206         int nn = query( 1, l, r, mid );
    207         if ( nn >= k )
    208         {
    209             ub = mid;
    210         }
    211         else
    212         {
    213             lb = mid + 1;
    214         }
    215     }
    216     return lb;
    217 }
    218 
    219 void clear( Node * o )
    220 {
    221     if ( o == NULL ) return ;
    222     clear( o->ch[0] );
    223     clear( o->ch[1] );
    224     delete o;
    225 }
    226 
    227 void del( int i )
    228 {
    229     if ( s[i].l == s[i].r )
    230     {
    231         delete s[i].rt;
    232         return ;
    233     }
    234     del( i << 1 );
    235     del( i << 1 | 1 );
    236     clear( s[i].rt );
    237 }
    238 
    239 int main ()
    240 {
    241     while ( scanf("%d", &n) != EOF )
    242     {
    243         for ( int i = 1; i <= n; i++ )
    244         {
    245             scanf("%d", &a[i]);
    246         }
    247         build( 1, 1, n );
    248         scanf("%d", &m);
    249         while ( m-- )
    250         {
    251             int op, x, y, k;
    252             scanf("%d", &op);
    253             if ( op == 1 )
    254             {
    255                 scanf("%d%d", &x, &y);
    256                 update( 1, x, y );
    257                 a[x] = y;
    258             }
    259             else
    260             {
    261                 scanf("%d%d%d", &x, &y, &k);
    262                 printf("%d
    ", kth( x, y, k ));
    263             }
    264         }
    265         del(1);
    266     }
    267     return 0;
    268 }
  • 相关阅读:
    CCF201604试题
    CCF201512试题
    CCF201509试题
    CCF201509试题
    CCF201503试题
    CCF201503试题
    CCF201412试题
    CCF201412试题
    CCF201409试题
    CCF201409试题
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4746139.html
Copyright © 2011-2022 走看看