• 教主的魔法[分块+二分]


    题目描述

    教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。

    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)

    CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。

    WD巨懒,于是他把这个回答的任务交给了你。

    输入输出格式

    输入格式:

    第1行为两个整数N、Q。Q为问题数与教主的施法数总和。

    第2行有N个正整数,第i个数代表第i个英雄的身高。

    第3到第Q+2行每行有一个操作:

    (1) 若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。

    (2) 若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。

    输出格式:

    对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。

    输入输出样例

    输入样例#1: 复制
    5 3
    
    1 2 3 4 5
    
    A 1 5 4
    
    M 3 5 1
    
    A 1 5 4
    输出样例#1: 复制
    2
    3
    

    说明

    【输入输出样例说明】

    原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。

    【数据范围】

    对30%的数据,N≤1000,Q≤1000。

    对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000

    题解

      分块+排序+二分

      首先我们把这个题目拆开来看:

      (1)要询问或给(l,r)加一个值

      (2)在(l,r)区间的值是不定值,还要求的是大于等于k的数有多少

      由(1)–>得尝试分块和分块的加法标记

      由(2)–>得我们可以事先处理好每一块的顺序,然后找到大于等于k的第一个数,就能求出每一块的贡献值了–>sort+vector

      要注意的是,当l,r处在两个不完整的块,暴力加上在排序就ok了

      ps:我用了stl,洛谷要开o2,或者考虑手打二分

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int n,m,tmp;
    int ch[1000005],bl[1000005],addx[1000005],l[1000005],r[1000005];
    vector<int>ve[5005];
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    void build()
    {
        for(int i=1;i<=tmp;i++)
        {
            l[i]=(i-1)*tmp+1;r[i]=tmp*i;
        }
        r[tmp]=n;
        for(int i=1;i<=n;i++)
        {
            bl[i]=(i-1)/(tmp)+1;
            ve[bl[i]].push_back(ch[i]);
        }
        for(int i=1;i<=bl[n];i++)
            sort(ve[i].begin(),ve[i].end());
    /*    for(int i=1;i<=bl[n];i++)
            for(int  j=0;j<ve[i].size();j++)
            cout<<ve[i][j]<<' ';*/
    }
    
    void change(int x)
    {
        ve[x].clear();
        for(int i=l[x];i<=r[x];i++)
            ve[x].push_back(ch[i]);
        sort(ve[x].begin(),ve[x].end()+1);
    }
    
    void add(int x,int y,int k)
    {
        if(bl[x]==bl[y])    for(int i=x;i<=y;i++)ch[i]+=k;
        else 
        {
            for(int i=x;i<=r[bl[x]];i++)ch[i]+=k;
            for(int i=l[bl[y]];i<=y;i++)ch[i]+=k;
        }
        change(bl[x]);change(bl[y]);
        for(int i=bl[x]+1;i<=bl[y]-1;i++)
        {    
            addx[i]+=k;
        }
    }
    
    int query(int x,int y,int k)
    {
        int ans=0;
    //    cout<<x<<' '<<y<<' '<<k<<endl;
        if(bl[x]==bl[y])for(int i=x;i<=y;i++){if(ch[i]+addx[bl[x]]>=k)ans++;}
        else 
        {
            for(int i=x;i<=r[bl[x]];i++){if(ch[i]+addx[bl[x]]>=k)ans++;}
            for(int i=l[bl[y]];i<=y;i++){if(ch[i]+addx[bl[y]]>=k)ans++;}
        }
        //    cout<<ans<<endl;
        for(int i=bl[x]+1;i<=bl[y]-1;i++)
        {
    //    cout<<".."<<endl;
            int xx=k-addx[i];
            int sum=lower_bound(ve[i].begin(),ve[i].end(),xx)-ve[i].begin();
            //cout<<sum<<endl;
            ans+=tmp-sum;
    //    cout<<ans<<endl;
        }
        return ans;
    }
    
    int main()
    {
        n=read();m=read();tmp=sqrt(n);if(tmp*tmp<n)tmp++;
        for(int i=1;i<=n;i++)
        {
            ch[i]=read();
        }
        build();
        for(int i=1;i<=m;i++)
        {
            char f;int x,y,z;
            cin>>f;x=read();y=read();z=read();
            if(f=='M')add(x,y,z);
            else printf("%d
    ",query(x,y,z));
        }
        return 0;
    }
  • 相关阅读:
    Vuex getters
    Vuex namespaced
    Vue 插槽 默认插槽 具名插槽 作用域插槽
    Vue 全局事件总线
    Vue $nextTick
    pubsubjs 消息订阅与发布
    js 解构赋值的连续写法 深层解构
    Vuex mapState mapGetters mapMutations mapActions
    QGIS在Windows上下载安装与建立空间数据库连接
    QGIS怎样设置简体中文以及新建可编辑的多边形的图层
  • 原文地址:https://www.cnblogs.com/hhh1109/p/8597749.html
Copyright © 2020-2023  润新知