• 区间最值差


    链接:http://poj.org/problem?id=3468

    难度不大,注意细节

     1 #include<cstdio> //分块,poj3468
     2 #include<algorithm>
     3 #include<cmath>
     4 #define ll long long
     5 #define N 100010
     6 using namespace std;
     7 ll a[N],sum[N],add[N];
     8 int L[N],R[N],d;
     9 int pos[N];
    10 int n,m,l,r;
    11 char op[3];
    12 
    13 void build(){//分块预处理 
    14     int t=sqrt(n*1.0);//float sqrt (float),double sqrt (double),double long sqrt(double long)
    15     int num=n/t;
    16     if(n%t)  num++;
    17     for(int i=1;i<=num;i++){
    18         L[i]=(i-1)*t+1;//每块的左右端点 
    19         R[i]=i*t;
    20     }
    21     R[num]=n; //最后一块的右端点为n 
    22     for(int i=1;i<=num;i++)
    23         for(int j=L[i];j<=R[i];j++){
    24             pos[j]=i;     //表示第j个元素属于第i块
    25             sum[i]+=a[j]; //计算每块和值
    26         }
    27 } 
    28 
    29 void change(int l,int r,long long d){//区间更新,[l,r]区间的元素加上d
    30     int p=pos[l],q=pos[r];//读所属块 
    31     if(p==q){//在一块中
    32         for(int i=l;i<=r;i++)//暴力修改 
    33             a[i]+=d;
    34         sum[p]+=d*(r-l+1);//修改和值 
    35     }
    36     else{
    37         for(int i=p+1;i<=q-1;i++)//中间完全覆盖块打懒标记 
    38             add[i]+=d;
    39         for(int i=l;i<=R[p];i++)//左端暴力修改 
    40             a[i]+=d;
    41         sum[p]+=d*(R[p]-l+1);
    42         for(int i=L[q];i<=r;i++)//右端暴力修改
    43             a[i]+=d;
    44         sum[q]+=d*(r-L[q]+1);//修改和值 
    45     }
    46 }
    47 
    48 ll query(int l,int r){//区间查询,查询[l,r]区间的元素和值 
    49     int p=pos[l],q=pos[r];
    50     ll ans=0;
    51     if(p==q){//在一块中
    52         for(int i=l;i<=r;i++)//累加 
    53             ans+=a[i];
    54         ans+=add[p]*(r-l+1);//计算懒标记 
    55     }
    56     else{
    57         for(int i=p+1;i<=q-1;i++)//累加中间块 
    58             ans+=sum[i]+add[i]*(R[i]-L[i]+1);
    59         for(int i=l;i<=R[p];i++)//左端暴力累加
    60             ans+=a[i];
    61         ans+=add[p]*(R[p]-l+1);
    62         for(int i=L[q];i<=r;i++)//右端暴力累加
    63             ans+=a[i];
    64         ans+=add[q]*(r-L[q]+1);//计算懒标记 
    65     }
    66     return ans;
    67 }
    68 
    69 int main(){
    70     scanf("%d%d",&n,&m);
    71     for(int i=1;i<=n;i++)
    72         scanf("%lld",&a[i]);
    73     build(); 
    74     for(int i=1;i<=m;i++){
    75         scanf("%s %d %d",op,&l,&r);
    76         if(op[0]=='C'){
    77             scanf("%d",&d);
    78             change(l,r,d);
    79         }
    80         else
    81             printf("%lld\n",query(l,r));
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    前端开发者也可以酷酷地开发桌面程序
    手把手教你怎么搭建angular+gulp的项目(一)
    在Angular中,如果权限值是异步请求所得,如何将其设置为HTTP请求头的Authorization?
    AngularJs ng-repeat指令中怎么实现含有自定义指令的动态html
    第一篇随笔,练练手
    我参与 Seata 开源项目的一些感悟
    一次 kafka 消息堆积问题排查
    图解 Kafka 水印备份机制
    Seata 动态配置订阅与降级实现原理
    记一次 Kafka 集群线上扩容
  • 原文地址:https://www.cnblogs.com/tflsnoi/p/16177909.html
Copyright © 2020-2023  润新知