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\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 }
线段树套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\n", kth( x, y, k )); 263 } 264 } 265 del(1); 266 } 267 return 0; 268 }