# 整体二分初探 两类区间第K大问题 poj2104 & hdu5412

 1 //#include <bits/stdc++.h>
2 #include <cstdio>
3 #include <cstring>
4 #include <cmath>
5 #include <algorithm>
6 using namespace std;
7 const int N = 1e5 + 10, Q = 5e3 + 10, lim = 1e9;
8 struct point
9 {
10     int x, num;
11 }a[N];
12 struct query
13 {
14     int x, y, k, cnt, num;
15 }q[Q], b[Q];
16 int sum[N], ans[Q];
17 int n, m;
18 bool cmp(const point &aa, const point &bb)
19 {
20     return aa.x < bb.x;
21 }
22 void calc(int ll, int rr, int rawL, int mid)
23 {
24     int L = 1, R = n + 1, MID;
25     while(L < R)
26     {
27         MID = (L + R) >> 1;
28         if(a[MID].x >= rawL)
29             R = MID;
30         else
31             L = MID + 1;
32     }
33     for(int i = R; i <= n && a[i].x <= mid; ++i)
34         for(int j = a[i].num; j <= n; j += (j & -j))
35             ++sum[j];
36     for(int i = ll; i <= rr; ++i)
37     {
38         q[i].cnt = 0;
39         for(int j = q[i].y; j; j -= (j & -j))
40             q[i].cnt += sum[j];
41         for(int j = q[i].x - 1; j; j -= (j & -j))
42             q[i].cnt -= sum[j];
43     }
44     for(int i = R; i <= n && a[i].x <= mid; ++i)
45         for(int j = a[i].num; j <= n; j += (j & -j))
46             --sum[j];
47 }
48 void divide(int ll, int rr, int rawL, int rawR)
49 {
50     if(rawL == rawR)
51     {
52         for(int i = ll; i <= rr; ++i)
53             ans[q[i].num] = rawR;
54         return;
55     }
56     int mid = rawL + ((rawR - rawL) >> 1);
57     calc(ll, rr, rawL, mid);
58     int now1 = ll, now2 = rr;
59     for(int i = ll; i <= rr; ++i)
60     {
61         if(q[i].cnt >= q[i].k)
62             b[now1++] = q[i];
63         else
64         {
65             q[i].k -= q[i].cnt;
66             b[now2--] = q[i];
67         }
68     }
69     for(int i = ll; i <= rr; ++i)
70         q[i] = b[i];
71     if(now1 != ll)
72         divide(ll, now1 - 1, rawL, mid);
73     if(now2 != rr)
74         divide(now2 + 1, rr, mid + 1, rawR);
75 }
76 int main()
77 {
78     scanf("%d%d", &n, &m);
79     for(int i = 1; i <= n; ++i)
80     {
81         scanf("%d", &a[i].x);
82         a[i].num = i;
83     }
84     a[n + 1].x = 2e9;
85     sort(a + 1, a + 1 + n, cmp);
86     for(int i = 1; i <= m; ++i)
87     {
88         scanf("%d%d%d", &q[i].x, &q[i].y, &q[i].k);
89         q[i].num = i;
90     }
91     divide(1, m, -lim, lim);
92     for(int i = 1; i <= m; ++i)
93         printf("%d\n", ans[i]);
94     return 0;
95 }

  1 #include <bits/stdc++.h>
2 using namespace std;
3 const int N = 1e5 + 10, Q = 1e5 + 10, A = N + Q * 2, lim = 1e9;
4 struct operate
5 {
6     int x, y, k, cnt, num;
7     operate(){}
8     operate(int _x, int _y, int _k, int _cnt, int _num)
9     {
10         x = _x;
11         y = _y;
12         k = _k;
13         cnt = _cnt;
14         num = _num;
15     }
16 }a[A], q1[A], q2[A];
17 int raw[N], ans[Q], sum[N];
18 int n, m, len, l1, l2;
19 void update(int x, int y)
20 {
21     for(int i = x; i <= n; i += (i & -i))
22         sum[i] += y;
23 }
24 int query(int x)
25 {
26     int re = 0;
27     for(int i = x; i; i -= (i & -i))
28         re += sum[i];
29     return re;
30 }
31 void calc(int ll, int rr, int rawl, int mid)
32 {
33     for(int i = ll; i <= rr; ++i)
34     {
35         if(a[i].k)
36             a[i].cnt = query(a[i].y) - query(a[i].x - 1);
37         else if(a[i].y <= mid)
38             update(a[i].x, a[i].cnt);
39     }
40     for(int i = ll; i <= rr; ++i)
41         if(!a[i].k && a[i].y <= mid)
42             update(a[i].x, -a[i].cnt);
43     l1 = l2 = 0;
44     for(int i = ll; i <= rr; ++i)
45         if(a[i].k)
46         {
47             if(a[i].k <= a[i].cnt)
48                 q1[++l1] = a[i];
49             else
50             {
51                 a[i].k -= a[i].cnt;
52                 q2[++l2] = a[i];
53             }
54         }
55         else
56         {
57             if(a[i].y <= mid)
58                 q1[++l1] = a[i];
59             else
60                 q2[++l2] = a[i];
61         }
62     int now = ll;
63     for(int i = 1; i <= l1; ++i)
64         a[now++] = q1[i];
65     for(int i = 1; i <= l2; ++i)
66         a[now++] = q2[i];
67 }
68 void divide(int ll, int rr, int rawl, int rawr)
69 {
70     if(rawl == rawr)
71     {
72         for(int i = ll; i <= rr; ++i)
73             if(a[i].k)
74                 ans[a[i].num] = rawl;
75         return;
76     }
77     int mid = (rawl + rawr) >> 1;
78     calc(ll, rr, rawl, mid);
79     int tmp = l1;
80     if(tmp)
81         divide(ll, ll + tmp - 1, rawl, mid);
82     if(ll + tmp <= rr)
83         divide(ll + tmp, rr, mid + 1, rawr);
84 }
85 int main()
86 {
87     while(scanf("%d", &n) != EOF)
88     {
89         len = 0;
90         for(int i = 1; i <= n; ++i)
91         {
92             scanf("%d", &raw[i]);
93             a[++len] = operate(i, raw[i], 0, 1, 0);
94          }
95          scanf("%d", &m);
96          int op, x, y, z;
97          for(int i = 1; i <= m; ++i)
98          {
99             scanf("%d", &op);
100             if(op & 1)
101             {
102                 scanf("%d%d", &x, &y);
103                 a[++len] = operate(x, raw[x], 0, -1, 0);
104                 a[++len] = operate(x, y, 0, 1, 0);
105                 raw[x] = y;
106                 ans[i] = 0;
107             }
108             else
109             {
110                 scanf("%d%d%d", &x, &y, &z);
111                 a[++len] = operate(x, y, z, 0, i);
112             }
113         }
114         divide(1, len, 1, lim);
115         for(int i = 1; i <= m; ++i)
116             if(ans[i])
117                 printf("%d\n", ans[i]);
118     }
119     return 0;
120 }

posted @ 2016-10-20 20:15  sagitta  阅读(3738)  评论(2编辑  收藏  举报