zoukankan      html  css  js  c++  java
  • [bzoj3343] 教主的魔法

    Description

    教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N
    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[LR](1≤LRN)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第LR)个英雄的身高)
    CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [LR] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
    WD巨懒,于是他把这个回答的任务交给了你。

    Input

           第1行为两个整数NQQ为问题数与教主的施法数总和。
           第2行有N个正整数,第i个数代表第i个英雄的身高。
           第3到第Q+2行每行有一个操作:
    (1)       若第一个字母为“M”,则紧接着有三个数字LRW。表示对闭区间 [LR] 内所有英雄的身高加上W
    (2)       若第一个字母为“A”,则紧接着有三个数字LRC。询问闭区间 [LR] 内有多少英雄的身高大于等于C

    Output

           对每个“A”询问输出一行,仅含一个整数,表示闭区间 [LR] 内身高大于等于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。

    思路

    分块,分成根n块,对于每个块,构建一个映射数组,转移原数组值,并排序,还有一个标记,储存增值;
    对于每次增值操作,对于整块,直接修改标记,对于非整块,暴力修改原数组,并重新构建映射数组;
    对于每次查询操作,对于整块,直接在映射数组中二分,对于非整块,暴力枚举;

    代码实现

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 const int maxn=1e6+10;
     5 const int maxm=1e3+10;
     6 int n,m,p;
     7 int s[maxn];
     8 int t[maxn],f[maxm];
     9 int search(int l,int r,int x){
    10     int ret=0;
    11     for(int i=l;i<=r;i++) if(s[i]>=x) ret++;
    12     return ret;
    13 }
    14 int find(int l,int r,int x){
    15     int mid,a=r;
    16     while(l!=r){
    17         mid=l+r>>1;
    18         if(t[mid]<x) l=mid+1;
    19         else r=mid;
    20     }
    21     if(t[l]<x) l++;
    22     return a-l+1;
    23 }
    24 void map(int l,int r){
    25     for(int i=l;i<=r;i++) t[i]=s[i];
    26     std::sort(t+l,t+r+1);
    27 }
    28 void add(int l,int r,int x){
    29     for(int i=l;i<=r;i++) s[i]+=x;
    30     map((l-1)/p*p+1,(r+p-1)/p*p);
    31 }
    32 int main(){
    33     scanf("%d%d",&n,&m),p=sqrt(n);
    34     for(int i=1;i<=n;i++) scanf("%d",&s[i]);
    35     for(int i=1;i<=n/p;i++) map((i-1)*p+1,i*p);
    36     if(n%p) map(n/p*p+1,n);
    37     int l,r,x,ans;char ch[3];
    38     while(m--){
    39         scanf("%s%d%d%d",ch,&l,&r,&x);
    40         if(ch[0]=='M'){
    41             if((l-1)/p==(r-1)/p){add(l,r,x);continue;}
    42             if(l%p!=1) add(l,((l-1)/p+1)*p,x);
    43             for(int i=(l+1)/p+1;i<=r/p;i++) f[i]+=x;
    44             if(r%p) add(r/p*p+1,r,x);
    45         }
    46         if(ch[0]=='A'){
    47             ans=0;
    48             if((l-1)/p==(r-1)/p) ans+=search(l,r,x-f[(r-1)/p+1]);
    49             else{
    50                 if(l%p!=1) ans+=search(l,((l-1)/p+1)*p,x-f[(l-1)/p+1]);
    51                 for(int i=(l+1)/p+1;i<=r/p;i++) ans+=find((i-1)*p+1,i*p,x-f[i]);
    52                 if(r%p!=0) ans+=search(r/p*p+1,r,x-f[r/p+1]);
    53             }
    54             printf("%d
    ",ans);
    55         }
    56     }
    57     return 0;
    58 }

    emmmmm,这题数据似乎非常水,反正我和洛谷里嘉诺巨型方块小数据都拍不过QUQ(当然是他们错啦:P)

    顺便,这是我第一次写分块,我真的太弱了QUQ

  • 相关阅读:
    Discuz X 2.5 点点(伪静态)
    jq 、xml 省市级联动
    php memcache 初级使用(2)
    关于windows虚拟内存管理的页目录自映射
    SharePoint 2010 网络上的开发经验和资源
    SharePoint 2010 Reporting Services 报表服务器正在内置 NT AUTHORITY\SYSTEM 账户下运行 解决方法
    SharePoint 2010 Reporting Services 报表服务器无法解密用于访问报表服务器数据库中的敏感数据或加密数据的对称密钥 解决方法
    Active Directory Rights Management Services (AD RMS)无法检索证书层次结构。 解决方法
    SharePoint 2010 Reporting Services 报表服务器实例没有正确配置 解决方法
    SharePoint 2010 页面引用 Reporting Services 展现 List 报表
  • 原文地址:https://www.cnblogs.com/J-william/p/8053426.html
Copyright © 2011-2022 走看看