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;
    }
    
  • 相关阅读:
    (备忘)解决用Xftp向CentOS7 传文件速度慢的问题
    CentOS上使用ntfs-3g挂载NTFS分区
    tomcat运行一段时间出“org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header”
    JQuery EasyUI treegrid展开与折叠,以及数据加载两次的问题
    goland 激活码
    golang 之xorm
    golang 之 go module
    golang 之单元测试
    golang 之反射
    golang 之sync &并发安全锁
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13771679.html
Copyright © 2011-2022 走看看