zoukankan      html  css  js  c++  java
  • whu 1464 Deal whth Numbers 线段树维护区间除法

    题意

      N个数,M个操作,操作有三类:

      1.  D,A,B,C  区间[a,b]中 大于0 的数 除以C,计算机整除

      2.  M,A,B,C  区间[a,b]所有数减去C

      3.  S,A,B     区间[a,b]求和

    解法

      区间更新和求和,线段树上延迟更新就可以了。主要是除法如何维护。

        这里的数C <= 5*1E5 , 因为大于0才除,所以每个数最多被除 log(Ai) 次, N个数则最多被除 N*log(Ai) 次了。

        所以做除法可以直接更新到底,还有就是使用一个标记,区间中都不可被除时,就没必要更新到底了。

      另外,除数是1的时候,不能除,貌似后台数据好多1,╮(╯▽╰)╭~~~

      

    View Code
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 typedef long long LL;
     8 
     9 const int N = 5e5+10;
    10 //segment_Tree
    11 #define lch rt<<1,l,m
    12 #define rch rt<<1|1,m+1,r
    13 LL sum[N<<2], add[N<<2];
    14 bool flag[N<<2];
    15 
    16 void push_up(int rt){
    17     sum[rt] = sum[rt<<1]+sum[rt<<1|1];
    18     flag[rt] = flag[rt<<1] | flag[rt<<1|1];    
    19 }
    20 void push_down(int rt,int L){
    21     if( add[rt] ){
    22         add[rt<<1] += add[rt];
    23         add[rt<<1|1] += add[rt];
    24         sum[rt<<1] += (L-(L>>1))*add[rt];
    25         sum[rt<<1|1] +=    (L>>1)*add[rt];
    26         add[rt] = 0;
    27     }    
    28 }
    29 void build(int rt,int l,int r){
    30     sum[rt] = add[rt] = 0;
    31     if(l == r){ scanf("%lld",&sum[rt]); flag[rt] = (sum[rt]>0); return; }
    32     int m = (l+r)>>1;
    33     build(lch), build(rch);
    34     push_up(rt);    
    35 }
    36 void Minus(int rt,int l,int r,int a,int b,int c){
    37     if(a <= l && r <= b){
    38         add[rt] += c; sum[rt] += (r-l+1)*c; return;    
    39     }
    40     push_down(rt,r-l+1);
    41     int m = (l+r)>>1;
    42     if( a <= m ) Minus( lch,a,b,c );
    43     if( m <  b ) Minus( rch,a,b,c );
    44     push_up(rt);
    45 }
    46 void Division(int rt,int l,int r,int a,int b,int c){
    47     if( flag[rt] == 0 ) return;
    48     if(l == r){
    49         if(sum[rt]>0) sum[rt] /= (LL)c; 
    50         flag[rt] = (sum[rt] > 0);     return;
    51     }    
    52     push_down(rt, r-l+1);
    53     int m = (l+r)>>1;
    54     if( a <= m ) Division( lch,a,b,c );
    55     if( m <  b ) Division( rch,a,b,c );
    56     push_up(rt);
    57 }
    58 LL Sum(int rt,int l,int r,int a,int b){
    59     if(a <= l && r <= b) return sum[rt];
    60     push_down(rt,r-l+1);
    61     int m = (l+r)>>1;
    62     LL res = 0;
    63     if( a <= m ) res += Sum(lch,a,b);
    64     if( m <  b ) res += Sum(rch,a,b);
    65     return res;    
    66 }
    67 
    68 int main(){
    69 //    freopen("D.in","r", stdin);
    70 //    freopen("test.out","w",stdout);
    71     int T;
    72     scanf("%d", &T);
    73     for(int Case = 1; Case <= T; Case++){
    74         int n, m, a, b, c;
    75         char op[10];
    76         scanf("%d%d", &n,&m);
    77         printf("Case %d:\n",Case);
    78         build( 1, 1, n );
    79         for(int i = 0; i < m; i++){
    80             scanf("%s", op);
    81             if( op[0] == 'D' ){
    82                 scanf("%d%d%d",&a,&b,&c);
    83                 if( c == 1 ) continue;
    84                 Division(1,1,n,a,b,c);     
    85             }
    86             else if( op[0] == 'M' ){
    87                 scanf("%d%d%d",&a,&b,&c);
    88                 Minus(1,1,n,a,b,-c);    
    89             }
    90             else{
    91                 scanf("%d%d",&a,&b);
    92                 LL res = Sum(1,1,n,a,b);
    93                 printf("%lld\n",res);
    94             }
    95         }    
    96         puts("");
    97     }
    98     return 0;    
    99 }
  • 相关阅读:
    PHP数组简介
    如何在不使用系统函数的情况下实现PHP中数组系统函数的功能
    弹性盒布局display:flex详解
    关于JS面向对象中原型和原型链以及他们之间的关系及this的详解
    如何使用AngularJS对表单提交内容进行验证
    如何用canvas画布画旋转的五角星
    MYSQL常用函数以及如何操作数据
    数据库基础以及表的创建
    PHP中的OOP
    PHP中数组的遍历
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3021460.html
Copyright © 2011-2022 走看看