zoukankan      html  css  js  c++  java
  • ZJOI2013 K大数查询

    题目链接

    Solution

    首先另 L = -n, R = n,那么 mid = (L + R) >> 1.考虑对于 mid 把所有操作(修改 / 查询)分为两类:dl 和 dr,使得两部分互不干扰。这样就可以把原问题拆成两个子问题,从而进行整体二分。

    考虑维护一个线段树,表示 [l,r] 区间有多少个数 > mid;

    对于修改操作:

    如果 c > mid,在线段树上对 [l,r] 整体 +1;这时候该操作可能对右区间产生贡献,因此放入 dr 内;

    如果 c <= mid,该操作可能对左区间产生贡献,因此放入 dl 内。

    对于查询操作:

    在线段树上查询 [l,r] 内有几个数 > mid,记为 res:

    如果 c > res,说明该询问的答案应该 < mid,因此把当前询问分入 dl 内;

    否则,说明当前询问的答案应该 >= mid,因此把当前询问放入 dr 内。

    总结一下,线段树需要支持如下两个操作:区间 +1,区间求和。

    其他一些具体细节在代码里(代码是抄的题解 qwq)

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    
    const LL N = 2333333;
    struct Que { LL opt, l, r, c, id; } q[N], dl[N], dr[N];
    LL n, m, num = 0, len1 = 0, len2 = 0, ql[N], qr[N], ans[N];
    
    struct SegmentTree
    {
        LL tag[N], sum[N];
        void push_up(LL x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
        void push_down(LL x, LL l, LL r)
        {
            if(tag[x] == 0) return ;
            LL mid = (l + r) >> 1;
            sum[x << 1] += tag[x] * (mid - l + 1);
            sum[x << 1 | 1] += tag[x] * (r - mid);
            tag[x << 1] += tag[x], tag[x << 1 | 1] += tag[x];
            tag[x] = 0;
        }
        void update(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
        {
            if(l > stdr || r < stdl) return ;
            if(stdl <= l && stdr >= r)
            {
                tag[x] += k;
                sum[x] += k * (r - l + 1);
                push_down(x, l, r);
                return ;
            }
            LL mid = (l + r) >> 1;
            push_down(x, l, r);
            update(x << 1, l, mid, stdl, stdr, k);
            update(x << 1 | 1, mid + 1, r, stdl, stdr, k);
            push_up(x), push_down(x, l, r);
        }
        LL query(LL x, LL l, LL r, LL stdl, LL stdr)
        {
            if(l > stdr || r < stdl) return 0;
            if(stdl <= l && stdr >= r) return sum[x];
            LL mid = (l + r) >> 1;
            push_down(x, l, r);
            return query(x << 1, l, mid, stdl, stdr) + 
            query(x << 1 | 1, mid + 1, r, stdl, stdr);
        }
    } tree;
    
    void work(LL st, LL ed, LL l, LL r)
    {
        LL lenl = 0, lenr = 0, Fl = 0, Fr = 0;
        if(l == r)
        {
            for(LL i = st; i <= ed; i++)
                if(q[i].opt == 2) ans[q[i].id] = l;
            return ;
        }
        LL mid = (l + r) >> 1;
        for(LL i = st; i <= ed; i++)
        {
            if(q[i].opt == 1)
                if(q[i].c > mid)
                {
                    tree.update(1, 1, n, q[i].l, q[i].r, 1);
                    dr[++lenr] = q[i];
                }
                else dl[++lenl] = q[i];
            else
            {
                LL res = tree.query(1, 1, n, q[i].l, q[i].r);
                if(res >= q[i].c) Fr = 1, dr[++lenr] = q[i];
                else
                {
                    Fl = 1, q[i].c -= res;
                    dl[++lenl] = q[i];
                }
            }
        }
        for(LL i = st; i <= ed; i++)
            if(q[i].opt == 1 && q[i].c > mid)
                tree.update(1, 1, n, q[i].l, q[i].r, -1);
        for(LL i = 1; i <= lenl; i++) q[st + i - 1] = dl[i];
        for(LL i = lenl + 1; i <= lenl + lenr; i++) q[st + i - 1] = dr[i - lenl];
        if(Fl == 1) work(st, st + lenl - 1, l, mid);
        if(Fr == 1) work(st + lenl, ed, mid + 1, r);
    } 
    
    int main()
    {
        scanf("%lld%lld", &n, &m);
        for(LL i = 1; i <= m; i++)
        {
            scanf("%lld%lld%lld%lld", &q[i].opt, &q[i].l, &q[i].r, &q[i].c);
            if(q[i].opt == 2) q[i].id = ++num;
        }
        work(1, m, -n, n);
        for(LL i = 1; i <= num; i++) printf("%lld
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    三个心态做人做学问 沧海
    成功走职场要找准自己的"快捷键" 沧海
    免费离线下载 拂晓风起
    Hibernate 获取某个表全部记录时 奇怪现象 (重复出现某个记录) 拂晓风起
    无法读取mdb 如果连接不了ACCESS mdb文件,就尝试安装MDAC 拂晓风起
    Netbeans 使用 Hibernate 逆向工程 生成hbm和pojo 拂晓风起
    如何点击单选框 radio 后面的文字,选中单选框 拂晓风起
    Java 连接access 使用access文件 不用配置 拂晓风起
    mysql下如何执行sql脚本 拂晓风起
    Hibernate配置access Hibernate 连接 access 拂晓风起
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13771679.html
Copyright © 2011-2022 走看看