zoukankan      html  css  js  c++  java
  • bzoj3343

    3343: 教主的魔法

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1178  Solved: 527
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Source

    分块裸题,每个块内排序维护顺序,修改时如果整块则打标记,否则暴力单点修改。查询每块二分查找lower_bound,然后拿块的右边界减一减,加入答案。

    下标不要搞错,pos[x] 和 x 坑了半天,小数据还拍不出来

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define N 1000010
    struct data
    {
        int num,tag;
    }d[N];
    int l[N],pos[N],r[N],tag[N];
    int n,q;
    bool cp(data x,data y)
    {
        return x.num+x.tag<y.num+y.tag;
    }
    void add(int a,int b,int delta)
    {
        while(a<=b)
        {
            if(a==l[pos[a]]&&b>=r[pos[a]])
            {
                d[pos[a]].tag+=delta;
            }
            else 
            {
                for(int i=a;i<=min(r[pos[a]],b);i++)
                    d[i].num+=delta;
                sort(d+l[pos[a]],d+r[pos[a]]+1,cp);
            }
            a=r[pos[a]]+1;
        }
    }
    int query(int a,int b,int delta)
    {
        int ret=0;
    //    printf("%d %d
    ",d[1].num,d[2].num);
        for(int i=a;i<=b;i=r[pos[i]]+1)
        {
            int ll=i,rr=min(r[pos[i]],b);
            while(rr-ll>1)
            {
                int mid=(ll+rr)/2;
                if(d[mid].num+d[pos[mid]].tag>=delta) rr=mid;
                else ll=mid;
            }
            while (d[ll].num+d[pos[ll]].tag<delta&&ll<=rr) ll++;
    //        printf("ll=%d r[pos[i]]=%d
    ",ll,r[pos[i]]);
            ret+=min(r[pos[i]],b)-ll+1;
        }    
        return ret;
    }
    int main()
    {
        memset(l,0x3f3f,sizeof(l));
        scanf("%d%d",&n,&q);
        int size=(int)(sqrt(n));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&d[i].num);
            pos[i]=(i-1)/size+1;
            l[pos[i]]=min(l[pos[i]],i);
            r[pos[i]]=max(r[pos[i]],i);
        }
        for(int i=1;i<=pos[n];i++)
        {
    //        printf("l=%d r=%d
    ",l[i],r[i]);
            sort(d+l[i],d+r[i]+1,cp);
        }
    //    for(int i=1;i<=n;i++)
    //    {
    //        printf("%d ",d[i].num);
    //    }
    //    printf("
    ");
        while(q--)
        {
            char s[10]; scanf("%s",s);
            int a,b,c; scanf("%d%d%d",&a,&b,&c);
            if(s[0]=='M') add(a,b,c);
            else printf("%d
    ",query(a,b,c));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    sql脚本:将一个数据库完整复制到另一个数据库(转)
    问题:DropDownList启用AutoPostback后,SelectedIndexChanged事件跟踪不到
    学习:如何在已有MOSS的环境下重装IIS(转)
    学习:MOSS2007 实现单点登陆(转)
    sql脚本:恢复数据库(根据备份的bak)(转)
    学习:深入浅出之正则表达式(转)
    错误:此网页的安全性验证无效并且可能损坏。请单击 Web 浏览器中的“后退”,刷新网页,再重试操作
    学习:关于代码调用SSP获取UserProfile出错的解决方案(转)
    问题:提升权限后,更新SPListItem即 Item.Update()出错问题
    学习:char、varchar、text和nchar、nvarchar、ntext的区别(转)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6201136.html
Copyright © 2011-2022 走看看