分治法:整体二分

整体二分主要是把所有询问放在一起二分答案,然后把操作也一起分治

当你发现多组询问可以离线的时候

当你发现询问可以二分答案而且check复杂度对于单组询问可以接受的时候

当你发现询问的操作都是一样的的时候

BZOJ3110

修改区间,查询区间第K大

 1 #include "cstdio"
 2 #define lowbit(x) (x & (-x)) 
 3  
 4 using namespace std;
 5  
 6 const int Nmax = 50005;
 7  
 8 int N, M;
 9 struct Option{
10     int sign, x, y, c;
11 }op[Nmax];
12  
13 int tot = -1, ans[Nmax];
14 int q[Nmax], tmp[2][Nmax];
15  
16 namespace BIT{
17     int t[Nmax][2], d[Nmax][2];
18  
19     void update(bool s, int pos, int c)
20     {
21         for (int i = pos; i <= N; i += lowbit(i)) {
22             if (t[i][s] != tot) { t[i][s] = tot; d[i][s] = 0; }
23             d[i][s] += c;
24         }
25     }
26      
27     int get_sum(bool s, int pos)
28     {
29         int res = 0;
30         for (int i = pos; i; i -= lowbit(i)) {
31             if (t[i][s] != tot) { t[i][s] = tot; d[i][s] = 0; }
32             res += d[i][s];
33         }
34         return res;
35     }
36      
37     void Add(int x, int y)
38     {
39         update(0, x, 1); update(0, y + 1, -1);
40         update(1, x, x); update(1, y + 1, -(y + 1));
41     }
42      
43     int Query(int x, int y)
44     {
45         int temp = get_sum(0, y) * (y + 1) - get_sum(1, y);
46         temp -= get_sum(0, x - 1) * x - get_sum(1, x - 1);
47         return temp;
48     }
49 }
50  
51 void solve(int L, int R, int l, int r)
52 {
53     if (L > R) return;
54      
55     ++tot; int mid = (l + r) >> 1;
56     if (l == r) {
57         for (int i = L; i <= R; ++i) if (op[q[i]].sign == 2) ans[q[i]] = mid;
58         return;
59     }
60      
61     tmp[0][0] = tmp[1][0] = 0; using namespace BIT;
62     for (int i = L; i <= R; ++i) {
63         int temp = q[i];
64         if (op[temp].sign == 1) {
65             if (op[temp].c <= mid) tmp[0][++tmp[0][0]] = temp;
66             else {
67                 tmp[1][++tmp[1][0]] = temp;
68                 Add(op[temp].x, op[temp].y);
69             }
70         } else {
71             int cnt = Query(op[temp].x, op[temp].y);
72             if (cnt < op[temp].c) {
73                 op[temp].c -= cnt;
74                 tmp[0][++tmp[0][0]] = temp;
75             } else tmp[1][++tmp[1][0]] = temp;
76         }
77     }
78      
79     int tl = L, t2 = L + tmp[0][0] - 1;
80     for (int i = 1; i <= tmp[0][0]; ++i) q[tl++] = tmp[0][i];
81     for (int i = 1; i <= tmp[1][0]; ++i) q[tl++] = tmp[1][i];
82     solve(L, t2, l, mid); solve(t2 + 1, R, mid + 1, r);
83 }
84  
85 int main()
86 {
87     scanf("%d%d", &N, &M);
88     for (int i = 1; i <= M; ++i) {
89         scanf("%d%d%d%d", &op[i].sign, &op[i].x, &op[i].y, &op[i].c);
90         q[i] = i;
91     }
92     solve(1, M, 1, N);
93     for (int i = 1; i <= M; ++i) {
94         if (op[i].sign == 2) printf("%d\n", ans[i]);
95     }
96      
97     return 0;
98 }

 

posted @ 2018-09-13 22:48  静听风吟。  阅读(182)  评论(0编辑  收藏  举报