zoukankan      html  css  js  c++  java
  • G

    题目链接:https://vjudge.net/contest/332656#problem/G

    题意:

    给你三种操作,三种输出方式:

    1.让l~r区间的所有值加c;

    2.让l~r区间的所有值乘c;

    3.让l~r区间的所有值变成c;

    4.让l~r区间的所有值都先求p(1~3)次方,然后求和输出。

    思路:

    这道题坑在有三种询问:set , add , mul。所以lazy标记要有三个,如果三个标记同时出现的处理方法——当更新set操作时,就把add标记和mul标记全部取消;当更新mul操作时,如果当前节点add标记存在,就把add标记改为:add * mul。这样的话就可以在PushDown()操作中先执行set,然后mul,最后add。

    sum1 = a1 + a2 + a3;

    sum2 = a1^2 + a2^2 + a3^2;

    sum3 = a1^3 + a2^3 + a3^3;

    如果每个元素都加c呢?

    sum1 = a1 + a2 + a3 + 3*c;

    sum2 = (a1 + c)^2 + (a2 + c) ^2 + (a3 + c)^2;

    sum3 = (a1 + c)^3 + (a2 + c) ^3 + (a3 + c)^3;

    式子分解一下不就好了

    sum2 = a1^2 + a2^2 + a3^2 + 2 * c * (a + b + c) + 3 * c^2;

    sum2 = 上一状态的sum2 + 2 * c * 上一状态的sum1 + 3 * c^2;

    sum3 = .....

    每个元素乘c,这个就很简单了,大家都懂,每个元素变成c也很好操作。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <vector>
      4 #include <cmath>
      5 #include <string>
      6 #include <string.h>
      7 #include <algorithm>
      8 using namespace std;
      9 #define LL __int64
     10 #define eps 1e-8
     11 #define INF INT_MAX
     12 #define lson l , m , rt << 1
     13 #define rson m + 1 , r , rt << 1 | 1
     14 const int MOD = 10007; 
     15 const int maxn = 100000 + 5;
     16 const int N = 12;
     17 LL add[maxn << 2] , set[maxn << 2] , mul[maxn << 2];
     18 LL sum1[maxn << 2] , sum2[maxn << 2] , sum3[maxn << 2];
     19 void PushUp(int rt)
     20 {
     21     sum1[rt] = (sum1[rt << 1] + sum1[rt << 1 | 1]) % MOD;
     22     sum2[rt] = (sum2[rt << 1] + sum2[rt << 1 | 1]) % MOD;
     23     sum3[rt] = (sum3[rt << 1] + sum3[rt << 1 | 1]) % MOD;
     24 }
     25 void build(int l , int r , int rt)
     26 {
     27     add[rt] = set[rt] = 0;
     28     mul[rt] = 1;
     29     if(l == r) {
     30         sum1[rt] = sum2[rt] = sum3[rt] = 0;
     31         return;
     32     }
     33     int m = (l + r) >> 1;
     34     build(lson);
     35     build(rson);
     36     PushUp(rt);
     37 }
     38 void PushDown(int rt , int len)
     39 {
     40     if(set[rt]) {
     41         set[rt << 1] = set[rt << 1 | 1] = set[rt];
     42         add[rt << 1] = add[rt << 1 | 1] = 0;    //注意这个也要下放
     43         mul[rt << 1] = mul[rt << 1 | 1] = 1;
     44         LL tmp = ((set[rt] * set[rt]) % MOD) * set[rt] % MOD;
     45         sum1[rt << 1] = ((len - (len >> 1)) % MOD) * (set[rt] % MOD) % MOD;
     46         sum1[rt << 1 | 1] = ((len >> 1) % MOD) * (set[rt] % MOD) % MOD;
     47         sum2[rt << 1] = ((len - (len >> 1)) % MOD) * ((set[rt] * set[rt]) % MOD) % MOD;
     48         sum2[rt << 1 | 1] = ((len >> 1) % MOD) * ((set[rt] * set[rt]) % MOD) % MOD;
     49         sum3[rt << 1] = ((len - (len >> 1)) % MOD) * tmp % MOD;
     50         sum3[rt << 1 | 1] = ((len >> 1) % MOD) * tmp % MOD;
     51         set[rt] = 0;
     52     }
     53     if(mul[rt] != 1) {    //这个就是mul[rt] != 1 , 当时我这里没注意所以TLE了
     54         mul[rt << 1] = (mul[rt << 1] * mul[rt]) % MOD;
     55         mul[rt << 1 | 1] = (mul[rt << 1 | 1] * mul[rt]) % MOD;
     56         if(add[rt << 1])    //注意这个也要下放
     57             add[rt << 1] = (add[rt << 1] * mul[rt]) % MOD;
     58         if(add[rt << 1 | 1])
     59             add[rt << 1 | 1] = (add[rt << 1 | 1] * mul[rt]) % MOD;
     60         LL tmp = (((mul[rt] * mul[rt]) % MOD * mul[rt]) % MOD);
     61         sum1[rt << 1] = (sum1[rt << 1] * mul[rt]) % MOD;
     62         sum1[rt << 1 | 1] = (sum1[rt << 1 | 1] * mul[rt]) % MOD;
     63         sum2[rt << 1] = (sum2[rt << 1] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
     64         sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
     65         sum3[rt << 1] = (sum3[rt << 1] % MOD) * tmp % MOD;
     66         sum3[rt << 1 | 1] = (sum3[rt << 1 | 1] % MOD) * tmp % MOD;
     67         mul[rt] = 1;
     68     }
     69     if(add[rt]) {
     70         add[rt << 1] += add[rt];    //add是+= , mul是*=
     71         add[rt << 1 | 1] += add[rt];
     72         LL tmp = (add[rt] * add[rt] % MOD) * add[rt] % MOD;        //注意sum3 , sum2 , sum1的先后顺序
     73         sum3[rt << 1] = (sum3[rt << 1] + (tmp * (len - (len >> 1)) % MOD) + 3 * add[rt] * ((sum2[rt << 1] + sum1[rt << 1] * add[rt]) % MOD)) % MOD;
     74         sum3[rt << 1 | 1] = (sum3[rt << 1 | 1] + (tmp * (len >> 1) % MOD) + 3 * add[rt] * ((sum2[rt << 1 | 1] + sum1[rt << 1 | 1] * add[rt]) % MOD)) % MOD;
     75         sum2[rt << 1] = (sum2[rt << 1] + ((add[rt] * add[rt] % MOD) * (len - (len >> 1)) % MOD) + (2 * sum1[rt << 1] * add[rt] % MOD)) % MOD;
     76         sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] + (((add[rt] * add[rt] % MOD) * (len >> 1)) % MOD) + (2 * sum1[rt << 1 | 1] * add[rt] % MOD)) % MOD;
     77         sum1[rt << 1] = (sum1[rt << 1] + (len - (len >> 1)) * add[rt]) % MOD;
     78         sum1[rt << 1 | 1] = (sum1[rt << 1 | 1] + (len >> 1) * add[rt]) % MOD;
     79         add[rt] = 0;
     80     }
     81 }
     82 void update(int L , int R , int c , int ch , int l , int r , int rt)
     83 {
     84     if(L <= l && R >= r) {
     85         if(ch == 3) {
     86             set[rt] = c;
     87             add[rt] = 0;
     88             mul[rt] = 1;
     89             sum1[rt] = ((r - l + 1) * c) % MOD;
     90             sum2[rt] = ((r - l + 1) * ((c * c) % MOD)) % MOD;
     91             sum3[rt] = ((r - l + 1) * (((c * c) % MOD) * c % MOD)) % MOD;
     92         } else if(ch == 2) {
     93             mul[rt] = (mul[rt] * c) % MOD;
     94             if(add[rt])
     95                 add[rt] = (add[rt] * c) % MOD;
     96             sum1[rt] = (sum1[rt] * c) % MOD;
     97             sum2[rt] = (sum2[rt] * (c * c % MOD)) % MOD;
     98             sum3[rt] = (sum3[rt] * ((c * c % MOD) * c % MOD)) % MOD;
     99         } else if(ch == 1) {
    100             add[rt] += c;
    101             LL tmp = (((c * c) % MOD * c) % MOD * (r - l + 1)) % MOD;    //(r - l + 1) * c^3
    102             sum3[rt] = (sum3[rt] + tmp + 3 * c * ((sum2[rt] + sum1[rt] * c) % MOD)) % MOD;
    103             sum2[rt] = (sum2[rt] + (c * c % MOD * (r - l + 1) % MOD) + 2 * sum1[rt] * c) % MOD;
    104             sum1[rt] = (sum1[rt] + (r - l + 1) * c) % MOD;
    105         }
    106         return;
    107     }
    108     PushDown(rt , r - l + 1);
    109     int m = (l + r) >> 1;
    110     if(L > m)
    111         update(L , R , c , ch , rson);
    112     else if(R <= m)
    113         update(L , R , c , ch , lson);
    114     else {
    115         update(L , R , c , ch , lson);
    116         update(L , R , c , ch , rson);
    117     }
    118     PushUp(rt);
    119 }
    120 LL query(int L , int R , int p , int l , int r , int rt)
    121 {
    122     if(L <= l && R >= r) {
    123         if(p == 1)
    124             return sum1[rt] % MOD;
    125         else if(p == 2)
    126             return sum2[rt] % MOD;
    127         else
    128             return sum3[rt] % MOD;
    129     }
    130     PushDown(rt , r - l + 1);
    131     int m = (l + r) >> 1;
    132     if(L > m)
    133         return query(L , R , p , rson);
    134     else if(R <= m)
    135         return query(L , R , p , lson);
    136     else 
    137         return (query(L , R , p , lson) + query(L , R , p , rson)) % MOD;
    138 }
    139 int main()
    140 {
    141     int n , m;
    142     int a , b , c , ch;
    143     while(~scanf("%d %d" , &n , &m))
    144     {
    145         if(n == 0 && m == 0)
    146             break;
    147         build(1 , n , 1);
    148         while(m--) {
    149             scanf("%d %d %d %d" , &ch , &a , &b , &c);
    150             if(ch != 4) {
    151                 update(a , b , c , ch , 1 , n , 1);
    152             } else {
    153                 printf("%I64d
    " , query(a , b , c , 1 , n , 1));
    154             }
    155         }
    156     }
    157     return 0;
    158 }
  • 相关阅读:
    当年偶然发现的 Java Bug(JDK 9及之前仍未修复)
    Centos 网卡命名规范及信息查看(物理网卡,虚拟网卡)
    Git 合并多个 commit,保持历史简洁
    Java 常用验证方法(commons-validator,hutool)
    Linux 日常操作(质量团队培训材料)
    Linux 帮助命令及工具(tldr,man,help,info)
    springmvc返回html页面解决方案
    二进制和十进制来回转换
    二进制按位与(&) 按位或(|) 异或运算(^)
    Spring容器和springmvc容器的区别联系
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11652235.html
Copyright © 2011-2022 走看看