• Bzoj 3343: 教主的魔法(分块+二分答案)


    3343: 教主的魔法
    Time Limit: 10 Sec Memory Limit: 256 MB
    Description
    教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。
    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)
    CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
    WD巨懒,于是他把这个回答的任务交给了你。
    Input
    第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。
    Output
    对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。
    Sample Input
    5 3
    1 2 3 4 5
    A 1 5 4
    M 3 5 1
    A 1 5 4
    Sample Output
    2
    3
    HINT
    【输入输出样例说明】
    原先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。

    /*
    分块+二分答案.
    对于小块,暴力搞. 
    对于整块打标记,二分查找.
    复杂度O(q√nlogn).
    (这么简单的题怎么一开始没想到呢QWQ.
    */
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define MAXN 1000001
    using namespace std;
    int n,m,q,ans,belong[MAXN],a[MAXN],s[MAXN],tag[MAXN];
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void pre(int x)
    {
        int l=(x-1)*m+1,r=min(x*m,n);
        for(int i=l;i<=r;i++) s[i]=a[i];
        sort(s+l,s+r+1);
        return ;
    }
    void change(int x,int y,int z)
    {
        for(int i=x;i<=min(belong[x]*m,y);i++) a[i]+=z;pre(belong[x]);
        if(belong[x]+1<belong[y])// 1 W.
          for(int i=belong[x]+1;i<=belong[y]-1;i++) tag[i]+=z;
        if(belong[x]!=belong[y])
        {
            for(int i=(belong[y]-1)*m+1;i<=y;i++) a[i]+=z;
            pre(belong[y]);
        }
    }
    int erfen(int x,int z)
    {
        int l=(x-1)*m+1,r=min(x*m,n);
        int p=lower_bound(s+l,s+r+1,z-tag[x])-s;
        return r-p+1;
    }
    void query(int x,int y,int z)
    {
        ans=0;
        for(int i=x;i<=min(belong[x]*m,y);i++)
          if(a[i]+tag[belong[i]]>=z) ans++;
        if(belong[x]+1<belong[y])
          for(int i=belong[x]+1;i<=belong[y]-1;i++) ans+=erfen(i,z);
        if(belong[x]!=belong[y])
        {
            for(int i=(belong[y]-1)*m+1;i<=y;i++)
              if(a[i]+tag[belong[i]]>=z) ans++;
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        int x,y,z;char ch[3];
        n=read(),q=read();
        m=sqrt(n);
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) belong[i]=(i-1)/m+1;
        for(int i=1;i<=belong[n];i++) pre(i);// 2 w.
        while(q--)
        {
            scanf("%s",ch);x=read(),y=read(),z=read();
            if(ch[0]=='M') change(x,y,z);
            else query(x,y,z);
        }
        return 0;
    }
  • 相关阅读:
    ubuntu上一些好的操作方式 习惯 文件备份
    ubuntu ufw 防火墙的设置
    ubuntu 的SSH 服务
    对一个数组的处理。
    ubuntu 的 crontab 计划任务
    django1.6 apache 项目部署.
    只此荒废的一个半个月。
    myeclipse python插件安装和环境配置(Windows7下)
    ubunt 12.04 64位 english 服务器版安装
    ubuntu sudo自动切换root 无需输入密码
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10067980.html
Copyright © 2020-2023  润新知