zoukankan      html  css  js  c++  java
  • [BZOJ3110][Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 9354  Solved: 2762 [Submit][Status][Discuss]

    Description

    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

    Input

    第一行N,M 接下来M行,每行形如1 a b c或2 a b c

    Output

    输出每个询问的结果

    Sample Input

    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3

    Sample Output

    1
    2
    1

    HINT

    【样例说明】
    第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
    的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
    1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
    大的数是 1 。‍

    N,M<=50000,N,M<=50000
    a<=b<=N
    1操作中abs(c)<=N
    2操作中c<=Maxlongint

    整体二分

    注意是第$K$大而不是第$K$小

    数据有负数要离散化

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    char buf[10000000], *ptr = buf - 1;
    inline int readint(){
        int n = 0;
        bool flag = false;
        while(*++ptr < '0' || *ptr > '9') if(*ptr == '-') flag = true;
        while(*ptr <= '9' && *ptr >= '0') n = (n << 1) + (n << 3) + (*ptr++ & 15);
        return flag ? -n : n;
    }
    typedef long long LL;
    const int maxn = 50000 + 10, maxm = 50000 + 10;
    int n, m;
    int num[maxm], ref[maxm], num_cnt;
    struct Bit{
        LL c1[maxn], c2[maxn];
        Bit(){
            memset(c1, 0, sizeof(c1));
            memset(c2, 0, sizeof(c2));
        }
        void Update(const int &pos, const LL &v1){
            LL v2 = (pos - 1) * v1;
            for(int i = pos; i <= n; i += i & -i){
                c1[i] += v1;
                c2[i] += v2;
            }
        }
        LL Query(const int &pos){
            LL s1 = 0, s2 = 0;
            for(int i = pos; i; i -= i & -i){
                s1 += c1[i];
                s2 += c2[i];
            }
            return pos * s1 - s2;
        }
    }bit;
    inline void Update(const int &l, const int &r, const LL &val){
        bit.Update(l, val);
        bit.Update(r + 1, -val);
    }
    inline LL Query(const int &l, const int &r){
        return bit.Query(r) - bit.Query(l - 1);
    }
    struct Que{
        int l, r, id;
        LL v;
        Que(){}
        Que(int _l ,int _r, LL _v, int _id): l(_l), r(_r), v(_v), id(_id){}
    }q[maxm];
    bool mark[maxm];
    int f[maxm], g[maxm];
    int ans[maxm], ans_cnt = 0;
    void solve(int ql, int qr, int vl, int vr){
        if(ql > qr) return;
        if(vl == vr){
            for(int i = ql; i <= qr; i++)
                ans[q[f[i]].id] = vl;
            return;
        }
        int mid = vl + vr + 1 >> 1, cnt = 0;
        LL t;
        for(int i = ql; i <= qr; i++){
            if(!q[f[i]].id){
                if(q[f[i]].v >= mid){
                    Update(q[f[i]].l, q[f[i]].r, 1);
                    mark[i] = true;
                    cnt++;
                }
                else mark[i] = false;
            }
            else{
                t = Query(q[f[i]].l, q[f[i]].r);
                if(t < q[f[i]].v){
                    mark[i] = false;
                    q[f[i]].v -= t;
                }
                else{
                    mark[i] = true;
                    cnt++;
                }
            }
        }
        int ll = ql, rr = ql + cnt;
        for(int i = ql; i <= qr; i++)
            if(mark[i]){
                g[ll++] = f[i];
                if(!q[f[i]].id) Update(q[f[i]].l, q[f[i]].r, -1);
            }
            else g[rr++] = f[i];
        for(int i = ql; i <= qr; i++) f[i] = g[i];
        solve(ql, ll - 1, mid, vr);
        solve(ll, qr, vl, mid - 1);
    }
    int main(){
        FILE* fin_handle = fopen("in.txt", "r");
        buf[fread(buf, sizeof(char), sizeof(buf), fin_handle)] = 0;
        freopen("out.txt", "w", stdout);
        n = readint();
        m = readint();
        for(int opt, a, b, c, i = 1; i <= m; i++){
            opt = readint();
            a = readint();
            b = readint();
            c = readint();
            if(opt == 1){
                q[i] = Que(a, b, (LL)c, 0);
                num[++num_cnt] = c;
            }
            else q[i] = Que(a, b, (LL)c, ++ans_cnt);
        }
        sort(num + 1, num + num_cnt + 1);
        num_cnt = unique(num + 1, num + num_cnt + 1) - (num + 1);
        for(int t, i = 1; i <= m; i++)
            if(!q[i].id){
                t = lower_bound(num + 1, num + num_cnt + 1, q[i].v) - num;
                ref[t] = q[i].v;
                q[i].v = t;
            }
        for(int i = 1; i <= m; i++) f[i] = i;
        solve(1, m, 1, num[num_cnt]);
        for(int i = 1; i <= ans_cnt; i++)
            printf("%d
    ", ref[ans[i]]);
        return 0;
    }
  • 相关阅读:
    servlet中调用注入spring管理的dao(转)
    java枚举类(转)
    压缩包太大导致的部署问题
    oracle数据泵导出导入
    全错位排列
    母函数及相关的算法题
    Effective Modern C++翻译(5)-条款4:了解如何观察推导出的类型
    Effective Modern C++翻译(4)-条款3:了解decltype
    Effective Modern C++翻译(3)-条款2:明白auto类型推导
    Effective Modern C++翻译(2)-条款1:明白模板类型推导
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7647519.html
Copyright © 2011-2022 走看看