zoukankan      html  css  js  c++  java
  • BZOJ 3110:[Zjoi2013]K大数查询(整体二分)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3110

    题意:……

    思路:其实和之前POJ那道题差不多,只不过是换成区间更新,而且是第k大不是第k小,第k大是降序的第k个,在二分询问的时候需要注意和第k小的不同细节。

    树状数组比线段树快了几倍,所以说树状数组区间更新区间查询是一个值得学的姿势啊。

    看了一下别人的,可以把插入时候的值换成n - x + 1,那么就可以变成找第k小了,输出的时候还要换回来。

    线段树:

     1 //9028 kb    7484 ms
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 #define N 50010
     7 #define lson rt<<1, l, m
     8 #define rson rt<<1|1, m + 1, r
     9 typedef long long LL;
    10 struct P {
    11     int type, l, r, id; LL val;
    12     P () {}
    13     P (int type, int l, int r, LL val, int id) : type(type), l(l), r(r), val(val), id(id) {}
    14 } q[N], lq[N], rq[N], qq[N];
    15 LL tree[N<<2], lazy[N<<2], ans[N];
    16 int n;
    17 
    18 void pushup(int rt) { tree[rt] = tree[rt<<1|1] + tree[rt<<1]; }
    19 
    20 void pushdown(int rt, int len) {
    21     if(lazy[rt]) {
    22         lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt];
    23         tree[rt<<1] += lazy[rt] * (len - (len >> 1)); tree[rt<<1|1] += lazy[rt] * (len >> 1);
    24         lazy[rt] = 0;
    25     }
    26 }
    27 
    28 void update(int rt, int l, int r, int L, int R, int val) {
    29     if(L <= l && r <= R) {
    30         tree[rt] += (r - l + 1) * val; // 居然漏了+1
    31         lazy[rt] += val; return ;
    32     }
    33     pushdown(rt, r - l + 1);
    34     int m = (l + r) >> 1;
    35     if(L <= m) update(lson, L, R, val);
    36     if(m < R) update(rson, L, R, val);
    37     pushup(rt);
    38 }
    39 
    40 LL query(int rt, int l, int r, int L, int R) {
    41     if(L <= l && r <= R) return tree[rt];
    42     pushdown(rt, r - l + 1);
    43     int m = (l + r) >> 1;
    44     LL ans = 0;
    45     if(L <= m) ans += query(lson, L, R);
    46     if(m < R) ans += query(rson, L, R);
    47     return ans;
    48 }
    49 
    50 void Solve(int l, int r, int lask, int rask) {
    51     if(rask < lask || r < l) return ;
    52     if(l == r) { for(int i = lask; i <= rask; i++) if(q[i].type == 2) ans[q[i].id] = l; return ; }
    53     int mid = (l + r) >> 1, lcnt = 0, rcnt = 0;
    54     for(int i = lask; i <= rask; i++) {
    55         if(q[i].type == 1) {
    56             if(mid >= q[i].val) { // 第k大 = 降序第k个,只更新比当前二分的答案大的
    57                 lq[++lcnt] = q[i];
    58             } else {
    59                 rq[++rcnt] = q[i];
    60                 update(1, 1, n, q[i].l, q[i].r, 1);
    61             }
    62         } else {
    63             LL num = query(1, 1, n, q[i].l, q[i].r);
    64             if(num >= q[i].val) rq[++rcnt] = q[i];
    65             else {
    66                 q[i].val -= num;
    67                 lq[++lcnt] = q[i];
    68             }
    69         }
    70     }
    71     for(int i = lask; i <= rask; i++) if(q[i].type == 1 && mid < q[i].val) update(1, 1, n, q[i].l, q[i].r, -1);
    72     for(int i = 1; i <= lcnt; i++) q[i+lask-1] = lq[i];
    73     for(int i = 1; i <= rcnt; i++) q[i+lask+lcnt-1] = rq[i];
    74     Solve(l, mid, lask, lask + lcnt - 1);
    75     Solve(mid + 1, r, lask + lcnt, rask);
    76 }
    77 
    78 int main() {
    79     int m, a, b, c, d, ins = 0, ask = 0;
    80     scanf("%d%d", &n, &m);
    81     for(int i = 1; i <= m; i++) {
    82         scanf("%d%d%d%d", &a, &b, &c, &d);
    83         if(a == 1) q[i] = P(a, b, c, d, ++ins);
    84         else q[i] = P(a, b, c, d, ++ask);
    85     }
    86     Solve(1, n, 1, m);
    87     for(int i = 1; i <= ask; i++)
    88         printf("%lld
    ", ans[i]);
    89     return 0;
    90 }

    树状数组:

     1 //1828ms    6.7MB
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 #define N 50010
     7 #define lson rt<<1, l, m
     8 #define rson rt<<1|1, m + 1, r
     9 typedef long long LL;
    10 struct P {
    11     int type, l, r, id; LL val;
    12     P () {}
    13     P (int type, int l, int r, LL val, int id) : type(type), l(l), r(r), val(val), id(id) {}
    14 } q[N], lq[N], rq[N], qq[N];
    15 LL bit[2][N], ans[N];
    16 int n;
    17 
    18 int lowbit(int x) { return x & (-x); }
    19 void Add(int i, int x, int w) { while(x <= n) bit[i][x] += w, x += lowbit(x); }
    20 LL Sum(int i, int x) { LL ans = 0; while(x) ans += bit[i][x], x -= lowbit(x); return ans; }
    21 void update(int l, int r, int w) {
    22     Add(0, l, w); Add(0, r + 1, -w); Add(1, l, w * l); Add(1, r + 1, -w * (r + 1));
    23 }
    24 LL query(int l, int r) {
    25     LL lsum = Sum(0, l - 1) * l - Sum(1, l - 1);
    26     LL rsum = Sum(0, r) * (r + 1) - Sum(1, r);
    27     return rsum - lsum;
    28 }
    29 
    30 void Solve(int l, int r, int lask, int rask) {
    31     if(rask < lask || r < l) return ;
    32     if(l == r) { for(int i = lask; i <= rask; i++) if(q[i].type == 2) ans[q[i].id] = l; return ; }
    33     int mid = (l + r) >> 1, lcnt = 0, rcnt = 0;
    34     for(int i = lask; i <= rask; i++) {
    35         if(q[i].type == 1) {
    36             if(mid >= q[i].val) { // 第k大 = 降序第k个,只更新比当前二分的答案大的
    37                 lq[++lcnt] = q[i];
    38             } else {
    39                 rq[++rcnt] = q[i];
    40                 update(q[i].l, q[i].r, 1);
    41             }
    42         } else {
    43             LL num = query(q[i].l, q[i].r);
    44             if(num >= q[i].val) rq[++rcnt] = q[i];
    45             else {
    46                 q[i].val -= num;
    47                 lq[++lcnt] = q[i];
    48             }
    49         }
    50     }
    51     for(int i = lask; i <= rask; i++) if(q[i].type == 1 && mid < q[i].val) update(q[i].l, q[i].r, -1);
    52     for(int i = 1; i <= lcnt; i++) q[i+lask-1] = lq[i];
    53     for(int i = 1; i <= rcnt; i++) q[i+lask+lcnt-1] = rq[i];
    54     Solve(l, mid, lask, lask + lcnt - 1);
    55     Solve(mid + 1, r, lask + lcnt, rask);
    56 }
    57 
    58 int main() {
    59     int m, a, b, c, d, ins = 0, ask = 0;
    60     scanf("%d%d", &n, &m);
    61     for(int i = 1; i <= m; i++) {
    62         scanf("%d%d%d%d", &a, &b, &c, &d);
    63         if(a == 1) q[i] = P(a, b, c, d, ++ins);
    64         else q[i] = P(a, b, c, d, ++ask);
    65     }
    66     Solve(1, n, 1, m);
    67     for(int i = 1; i <= ask; i++)
    68         printf("%lld
    ", ans[i]);
    69     return 0;
    70 }

     第k小:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define N 50010
     6 #define lson rt<<1, l, m
     7 #define rson rt<<1|1, m + 1, r
     8 typedef long long LL;
     9 struct P {
    10     int type, l, r, id; LL val;
    11     P () {}
    12     P (int type, int l, int r, LL val, int id) : type(type), l(l), r(r), val(val), id(id) {}
    13 } q[N], lq[N], rq[N], qq[N];
    14 LL bit[2][N], ans[N];
    15 int n;
    16 
    17 int lowbit(int x) { return x & (-x); }
    18 void Add(int i, int x, int w) { while(x <= n) bit[i][x] += w, x += lowbit(x); }
    19 LL Sum(int i, int x) { LL ans = 0; while(x) ans += bit[i][x], x -= lowbit(x); return ans; }
    20 void update(int l, int r, int w) {
    21     Add(0, l, w); Add(0, r + 1, -w); Add(1, l, w * l); Add(1, r + 1, -w * (r + 1));
    22 }
    23 LL query(int l, int r) {
    24     LL lsum = Sum(0, l - 1) * l - Sum(1, l - 1);
    25     LL rsum = Sum(0, r) * (r + 1) - Sum(1, r);
    26     return rsum - lsum;
    27 }
    28 
    29 void Solve(int l, int r, int lask, int rask) {
    30     if(rask < lask || r < l) return ;
    31     if(l == r) { for(int i = lask; i <= rask; i++) if(q[i].type == 2) ans[q[i].id] = l; return ; }
    32     int mid = (l + r) >> 1, lcnt = 0, rcnt = 0;
    33     for(int i = lask; i <= rask; i++) {
    34         if(q[i].type == 1) {
    35             if(mid >= q[i].val) { // 第k大 = 降序第k个,只更新比当前二分的答案大的
    36                 lq[++lcnt] = q[i];
    37                 update(q[i].l, q[i].r, 1);
    38             } else {
    39                 rq[++rcnt] = q[i];
    40             }
    41         } else {
    42             LL num = query(q[i].l, q[i].r);
    43             if(num >= q[i].val) lq[++lcnt] = q[i];
    44             else {
    45                 q[i].val -= num;
    46                 rq[++rcnt] = q[i];
    47             }
    48         }
    49     }
    50     for(int i = lask; i <= rask; i++) if(q[i].type == 1 && mid >= q[i].val) update(q[i].l, q[i].r, -1);
    51     for(int i = 1; i <= lcnt; i++) q[i+lask-1] = lq[i];
    52     for(int i = 1; i <= rcnt; i++) q[i+lask+lcnt-1] = rq[i];
    53     Solve(l, mid, lask, lask + lcnt - 1);
    54     Solve(mid + 1, r, lask + lcnt, rask);
    55 }
    56 
    57 int main() {
    58     int m, a, b, c, d, ins = 0, ask = 0;
    59     scanf("%d%d", &n, &m);
    60     for(int i = 1; i <= m; i++) {
    61         scanf("%d%d%d%d", &a, &b, &c, &d);
    62         if(a == 1) q[i] = P(a, b, c, n - d + 1, ++ins);
    63         else q[i] = P(a, b, c, d, ++ask);
    64     }
    65     Solve(1, 2 * n + 1, 1, m);
    66     for(int i = 1; i <= ask; i++)
    67         printf("%lld
    ", n - ans[i] + 1);
    68     return 0;
    69 }
  • 相关阅读:
    云原生范式转变:您准备好了吗?
    CentOS 6.x 开机 自启动 脚本
    忠告 程序员 先思考再编程,累的时候不要写代码
    服务化架构组件清单
    代码自动修复
    选择塑造人生
    mariadb change password
    Spring 集成 Druid Monitor URL 配置转义问题(xml or properties)
    挣钱 vs. 花钱
    管理的要义
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6286747.html
Copyright © 2011-2022 走看看