码迷,mamicode.com
首页 > 其他好文 > 详细

zoj 2112 块状链表求动态第k大

时间:2015-08-20 20:34:46      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:

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

  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\n", 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 }

 

zoj 2112 块状链表求动态第k大

标签:

原文地址:http://www.cnblogs.com/huoxiayu/p/4746139.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!