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

  • 相关阅读:
    理解jquery的$.extend()、$.fn和$.fn.extend()
    前端跨域请求原理及实践
    [leetcode]Minimum Path Sum
    [leetcode]Jump Game II
    [leetcode]Merge Intervals
    [leetcode]Length of Last Word
    [leetcode]Unique Paths
    [leetcode]Text Justification
    [leetcode]Binary Tree Level Order Traversal
    [leetcode]Jump Game
  • 原文地址:https://www.cnblogs.com/J-william/p/8053426.html
Copyright © 2011-2022 走看看