• BZOJ_3343_教主的魔法_分块+二分查找


    BZOJ_3343_教主的魔法_分块+二分查找

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

    分析:分块。

    每一块用一个辅助数组来排序,询问时整块二分查找大于等于C的位置,零散的暴力重构。

    重构时可以归并也可以直接sort

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    #define N 1000010
    #define LL long long
    void read(LL &x){
        int f=1;x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
        x*=f;
    }
    int L[1010],R[1010],pos[N],t,is[1010],add[1010],n,q;
    LL a[N],b[N];
    int find(int blo,LL x){
        int l=L[blo],r=R[blo]+1;
        while(l<r){
            int mid=l+r>>1;
            if(b[mid]<x)l=mid+1;
            else r=mid;
        }return R[blo]-l+1;
    }
    inline void pre(int blo){
        for(int i=L[blo];i<=R[blo];i++)b[i]=a[i];
        sort(b+L[blo],b+R[blo]+1);
    }
    void up(int l,int r,LL c){
        int p=pos[l],q=pos[r];
        if(p==q){
            for(int i=l;i<=r;i++){
                a[i]+=c;
            }
            pre(p);
        }else{
            for(int i=p+1;i<q;i++){
                add[i]+=c;
            }
            for(int i=l;i<=R[p];i++){
                a[i]+=c;
            }
            for(int i=L[q];i<=r;i++){
                a[i]+=c;
            }
            pre(p);pre(q);
        }
    }
    int query(int l,int r,LL c){
        int p=pos[l],q=pos[r];
        int ans=0;
        if(p==q){
            for(int i=l;i<=r;i++)if(a[i]+add[p]>=c)ans++;
        }else{
            for(int i=p+1;i<q;i++){
                ans+=find(i,c-add[i]);
            }
            for(int i=l;i<=R[p];i++){
                if(a[i]+add[p]>=c)ans++;
            }
            for(int i=L[q];i<=r;i++){
                if(a[i]+add[q]>=c)ans++;
            }
        }
        return ans;
    }
    char op[10];
    int main(){
        scanf("%d%d",&n,&q);
        t=sqrt(n);
        for(int i=1;i<=t;i++){
            L[i]=R[i-1]+1,R[i]=t*i;
            for(int j=L[i];j<=R[i];j++){
                read(a[j]);pos[j]=i;
            }
        }
        if(n-t*t){
            t++;L[t]=R[t-1]+1;R[t]=n;
            for(int i=L[t];i<=R[t];i++){
                read(a[i]);pos[i]=t;
            }
        }
        for(int i=1;i<=t;i++)pre(i);
        int x,y,z;
        while(q--){
            scanf("%s%d%d%d",op,&x,&y,&z);
            if(op[0]=='M'){
                up(x,y,1ll*z);
            }else{
                printf("%d
    ",query(x,y,1ll*z));
            }
        }
    }
    
  • 相关阅读:
    将微信小程序上传到公司的账号下
    当HBuilderX运行时打不开微信开发者工具时
    vue路径中去掉#
    初次快速使用git
    小米商城应用效果(阴影效果)
    如何使用hover点击一个元素使另一个颜色变色
    Open browser failed!! Please check if you have installed the browser correct
    vue中解决跨域问题
    vue中如何实现点击动态切换样式
    es5中数组的迭代方法 forEach,map,filter,some,every
  • 原文地址:https://www.cnblogs.com/suika/p/8457529.html
Copyright © 2020-2023  润新知