码迷,mamicode.com
首页 > 编程语言 > 详细

主席树套树状数组 动态区间第k小

时间:2015-04-15 00:37:55      阅读:393      评论:0      收藏:0      [点我收藏+]

标签:

先打上代码以后更新解释

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #define REP(i, s, n) for(int i = s; i <= n; i ++)
 7 #define RAP(i, n, s) for(int i = n; i >= s; i --)
 8 #define LOW for(; x; x -= x & (-x))
 9 using namespace std;
10 const int maxn = 100000 + 10;
11 const int Maxn = 100000;
12 const int maxnode = 200 * maxn;
13 int s[maxnode], ls[maxnode], rs[maxnode], A[maxn], root[maxn], Ln, Rn, L[maxn], R[maxn], c[maxn];
14 int n, Q, ms = 0;
15 void update(int x, int& y, int L, int R, int pos, int v){
16     s[y = ++ ms] = s[x] + v;
17     if(L == R) return ;
18     int M = L + R >> 1;
19     ls[y] = ls[x]; rs[y] = rs[x];
20     if(pos <= M) update(ls[x], ls[y], L, M, pos, v);
21     else update(rs[x], rs[y], M + 1, R, pos, v);
22     return ;
23 }
24 void update(int x, int v){
25     for(int i = x; i <= Maxn; i += i & (-i)) update(c[i], c[i], 1, Maxn, A[x], -1); A[x] = v;
26     for(int i = x; i <= Maxn; i += i & (-i)) update(c[i], c[i], 1, Maxn, A[x], 1); return ;
27 }
28 void init(int x, int tp){
29     if(!tp) { L[++ Ln] = root[x]; LOW if(c[x]) L[++ Ln] = c[x]; }
30     else { R[++ Rn] = root[x]; LOW if(c[x]) R[++ Rn] = c[x]; }
31     return ;
32 }
33 int query(int ql, int qr, int k){
34     Ln = Rn = 0; init(qr, 1); init(ql - 1, 0);//0是左
35     int ll = 1, rr = Maxn;
36     while(ll < rr){
37         int Lsum = 0, Rsum = 0, M = ll + rr >> 1;
38         REP(i, 1, Ln) Lsum += s[ls[L[i]]];
39         REP(i, 1, Rn) Rsum += s[ls[R[i]]];
40         int kth = Rsum - Lsum;
41         if(kth >= k){//往左找 
42             REP(i, 1, Ln) L[i] = ls[L[i]];
43             REP(i, 1, Rn) R[i] = ls[R[i]];
44             rr = M;
45         }
46         else{//往右找 
47             REP(i, 1, Ln) L[i] = rs[L[i]];
48             REP(i, 1, Rn) R[i] = rs[R[i]];
49             ll = M + 1; k -= kth; //看好了二分! 别忘了还要减 Σ( ° △ °|||)︴ 
50         }
51     }
52     return ll;
53 }
54 inline void read(int &x){
55     x = 0; int sig = 1; char ch = getchar();
56     while(!isdigit(ch)) { if(ch == -) sig = -1; ch = getchar(); }
57     while(isdigit(ch)) x = 10 * x + ch - 0, ch = getchar();
58     x *= sig; return ;
59 }
60 inline void write(int x){
61     if(x == 0) { putchar(0); return ; }
62     if(x < 0) putchar(-), x = -x;
63     int len = 0, buf[20];
64     while(x) buf[len ++] = x % 10, x /= 10;
65     RAP(i, len - 1, 0) putchar(buf[i] + 0); return ;
66 }
67 void init(){
68     read(n); read(Q);
69     REP(i, 1, n) read(A[i]);
70     REP(i, 1, n) update(root[i - 1], root[i], 1, Maxn, A[i], 1);
71     return ;
72 }
73 void work(){
74     int tp, ql, qr, k, x, v;
75     while(Q --){
76         read(tp);
77         if(tp) read(ql), read(qr), read(k), write(query(ql, qr, k) - 1), putchar(\n);// 减一 
78         else read(x), read(v), update(x, v);
79     }
80     return ;
81 }
82 void print(){
83 
84     return ;
85 }
86 int main(){
87     init();
88     work();
89     print();
90     return 0;
91 }

 

主席树套树状数组 动态区间第k小

标签:

原文地址:http://www.cnblogs.com/chxer/p/4427235.html

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