zoukankan      html  css  js  c++  java
  • 分治法:整体二分

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

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

    当你发现询问可以二分答案而且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
    ", ans[i]);
    95     }
    96      
    97     return 0;
    98 }
  • 相关阅读:
    数值的整数次方
    二进制中1的个数
    SpingBoot 启动自动给MongoDB建库
    Java 依赖冲突的解决办法
    Http协议
    你被限流了吗?
    LeetCode 783. 二叉搜索树节点最小距离
    Leetcode 687. 最长同值路径
    LeetCode 784. 字母大小写全排列
    LeetCode 面试题 08.06. 汉诺塔问题
  • 原文地址:https://www.cnblogs.com/aininot260/p/9643727.html
Copyright © 2011-2022 走看看