• 「BZOJ3343」教主的魔法(分块+二分查找)


    题意:

    给定一个数列,您需要支持以下两种操作:
    给[l,r]同加一个数
    询问[l,r]中有多少数字大于或等于v

    (n<=1000000,m<=3000)

    题解

    块内排序二分查询
    修改就用个数组存整块的修改值
    不完整的部分都暴力修改和查询
    时间复杂度大概O(Qsqrt(n)logn)

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1001000; 
     8 int n,m,a[N],b[N],block[N],L[2000],R[2000],cnt[2000],ans,Block;
     9 int find(int x,int y){
    10     int l=L[x];int r=R[x];
    11     int tmp=9999999;
    12     while(l<=r){
    13         int mid=(l+r)>>1;
    14         if(b[mid]>=y){
    15             tmp=mid;
    16             r=mid-1;
    17         }
    18         else l=mid+1;
    19     }
    20     return max(0,R[x]-tmp+1);
    21 }
    22 int main(){
    23     scanf("%d%d",&n,&m);
    24     Block=sqrt(n);
    25     for(int i=1;i<=n;i++){
    26         scanf("%d",&a[i]);
    27         b[i]=a[i];
    28         block[i]=(i-1)/Block+1;
    29         if(!L[block[i]])L[block[i]]=i;
    30         R[block[i]]=i;
    31     }
    32     for(int i=1;i<=block[n];i++)sort(b+L[i],b+1+R[i]);
    33     char s[10];
    34     while(m--){
    35         scanf("%s",s);
    36         if(s[0]=='A'){
    37             int l,r,c;
    38             ans=0;
    39             scanf("%d%d%d",&l,&r,&c);
    40             if(block[l]==block[r]){
    41                 for(int i=l;i<=r;i++)if(a[i]+cnt[block[i]]>=c)ans++;
    42                 printf("%d
    ",ans);
    43                 continue;
    44             }
    45             for(int i=l;i<=R[block[l]];i++)if(a[i]+cnt[block[i]]>=c)ans++;
    46             for(int i=L[block[r]];i<=r;i++)if(a[i]+cnt[block[i]]>=c)ans++;
    47             if(block[l]+1<block[r])
    48                 for(int i=block[l]+1;i<=block[r]-1;i++)ans+=find(i,c-cnt[i]);
    49             printf("%d
    ",ans);
    50         }
    51         else{
    52             int l,r,c;
    53             scanf("%d%d%d",&l,&r,&c);
    54             if(block[l]+1<block[r])
    55                 for(int i=block[l]+1;i<=block[r]-1;i++)cnt[i]+=c;
    56             for(int i=l;i<=R[block[l]];i++)a[i]+=c;
    57             for(int i=L[block[l]];i<=R[block[l]];i++)b[i]=a[i];
    58             sort(b+L[block[l]],b+1+R[block[l]]);
    59             for(int i=L[block[r]];i<=r;i++)a[i]+=c;
    60             for(int i=L[block[r]];i<=R[block[r]];i++)b[i]=a[i];
    61             sort(b+L[block[r]],b+1+R[block[r]]);
    62         }
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    SpringCloud Gateway使用实例
    Nacos服务注册与发现
    HashMap源码分析——put方法
    Volatile关键字——内存可见性
    Java的JIT编译器
    why spring?
    mysql 锁
    sql server 表变量和临时表
    mysql 存储过程
    mysql 截取字符串
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9480534.html
Copyright © 2020-2023  润新知