• [ZJOI2013]K大数查询


    [ZJOI2013]K大数查询

    题目描述

    有N个位置,M个操作。操作有两种,每次操作如果是:

    • 1 a b c:表示在第a个位置到第b个位置,每个位置加上一个数c
    • 2 a b c:表示询问从第a个位置到第b个位置,第C大的数是多少。

    输入输出格式

    输入格式:

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

    输出格式:

    输出每个询问的结果


    solution

    整体二分。

    假设我们现在要解决[ql,qr] 并且他们的答案(加数操作就是值)在[l,r]

    二分一个mid,我们维护一个区间。

    我们把>=mid的操作对应区间都加1

    对于询问,如果对应区间的值>=c,说明mid-r有最少c个了,那么它的答案就在[mid,r]里。

    否则把值减去区间对应值,丢进[l,mid-1]里。

    树状数组有个高级的区间加区间查写法,维护差分和差分*i

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 500005
    using namespace std;
    int n,m,Max,t1[maxn],t2[maxn];
    struct node{
        int op,a,b,c,id,ans;
    }q[maxn],s[maxn];
    void add(int x,int v){
        for(int i=x;i<=n;i+=i&-i)t1[i]+=v,t2[i]+=x*v;
    }
    int ask(int x){
        int sum=0;
        for(int i=x;i;i-=i&-i){
            sum+=(x+1)*t1[i]-t2[i];
        }
        return sum;
    }
    void solve(int l,int r,int ql,int qr){
        if(l==r){
            for(int i=ql;i<=qr;i++)q[i].ans=l;
            return;
        }
        int mid=l+r+1>>1;
        int p=ql;
        for(int i=ql;i<=qr;i++){
            if(q[i].op==1){
                if(q[i].c>=mid){
                    add(q[i].a,1);add(q[i].b+1,-1);
                }
                else p++;
            }
            else {
                q[i].ans=ask(q[i].b)-ask(q[i].a-1);
                if(q[i].ans<q[i].c)p++;
            }
        }
        int n1=ql,n2=p;
        for(int i=ql;i<=qr;i++){
            if(q[i].op==1){
                if(q[i].c>=mid){
                    add(q[i].a,-1);add(q[i].b+1,1);
                    s[n2++]=q[i];
                }
                else s[n1++]=q[i];
            }
            else {
                if(q[i].ans<q[i].c){
                    q[i].c-=q[i].ans;
                    s[n1++]=q[i];
                }
                else s[n2++]=q[i];
            }
        }
        for(int i=ql;i<=qr;i++)q[i]=s[i];
        solve(l,mid-1,ql,p-1);solve(mid,r,p,qr);
    }
    bool ID(node a,node b){return a.id<b.id;}
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&q[i].op,&q[i].a,&q[i].b,&q[i].c);
            Max=max(Max,q[i].c);
            q[i].id=i;
        }
        solve(1,Max,1,m);
        sort(q+1,q+m+1,ID);
        for(int i=1;i<=m;i++){
            if(q[i].op==2){
                printf("%d
    ",q[i].ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    从零打造树莓派智能助手(一)——让树莓派说话
    以np.concatenate为主题,谈谈numpy数组按维度合并的问题
    树莓派apt报错:E: 'Release' 这个值对 APT::Default-Release 是无效的,因为在源里找不到这样的发行
    我遇到的一些Git问题汇编
    在Mac平台用Sublime编辑器使用Git并连接github
    LeetCode108——Convert Sorted Array to Binary Search Tree
    LeetCode122——Best Time to Buy and Sell Stock II
    LeetCode686——Repeated String Match
    Python爬虫 — 百度翻译
    HTTP 协议
  • 原文地址:https://www.cnblogs.com/liankewei/p/10410432.html
Copyright © 2020-2023  润新知