HDU 4578 Transformation

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4578

----------------------------------------------------------------------------------

一道操作比较复杂的线段树的题目

强烈建议线段树写得比较少的同学把操作$1,2,3$一个一个地加上去

直接写三个操作思路可能比较乱

这题是求区间$1$到$3$次方的和 对于1操作 需要推导下如何更新

假设区间长度为$len 1,2,3 $次方的和分别为$ sum1$ $sum2$ $sum3$

更新后为$ sum1'$ $sum2'$ $sum3' $那么

$sum1' = sum1 + c * len$

$sum2' = sum2 + sum1 * c * 2 +  c * c * len$

$sum3' = sum3 + sum2 * c * 3 + sum1 * c * c * 3 + c * c * c * len$

其他部分都还好 就是要耐心一点去分析 代码量只有$2K+$

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <algorithm>
  5 using namespace std;
  6 const int N = 100010, mod = 10007;
  7 int sum[3][N << 2], flag[3][N << 2];
  8 int n, m;
  9 void update(int x, int L, int R, int tl, int tr, int o, int c);
 10 void build(int x, int tl, int tr)
 11 {
 12     sum[0][x] = sum[1][x] = sum[2][x] = 0;
 13     flag[0][x] = flag[2][x] = 0;
 14     flag[1][x] = 1;
 15     if(tl == tr)
 16         return;
 17     int mid = (tl + tr) >> 1;
 18     build(x << 1, tl, mid);
 19     build(x << 1 | 1, mid + 1, tr);
 20 }
 21 void pushdown(int x, int tl, int tr)
 22 {
 23     int mid = (tl + tr) >> 1;
 24     for(int i = 2; i >= 0; --i)
 25         if(flag[i][x] && !(i == 1 && flag[i][x] == 1))
 26         {
 27             update(x << 1, tl, mid, tl, mid, i, flag[i][x]);
 28             update(x << 1 | 1, mid + 1, tr, mid + 1, tr, i, flag[i][x]);
 29             flag[i][x] = (i == 1 ? 1 : 0);
 30         }
 31 }
 32 void update(int x, int L, int R, int tl, int tr, int o, int c)
 33 {
 34     int mid = (tl + tr) >> 1;
 35     if(L <= tl && tr <= R)
 36     {
 37         if(o == 0)
 38         {
 39             flag[0][x] = (flag[0][x] + c) % mod;
 40             sum[2][x] = (sum[2][x] + sum[1][x] * c * 3 % mod
 41             + sum[0][x] * c % mod * c * 3 % mod + c * c % mod * c % mod * 
 42             (tr - tl + 1) % mod) % mod;
 43             sum[1][x] = (sum[1][x] + sum[0][x] * c * 2 % mod + c * c % mod *
 44             (tr - tl + 1) % mod) % mod;
 45             sum[0][x] = (sum[0][x] + c * (tr - tl + 1) % mod) % mod; 
 46         }
 47         else if(o == 1)
 48         {
 49             flag[0][x] = flag[0][x] * c % mod;
 50             flag[1][x] = flag[1][x] * c % mod;
 51             sum[0][x] = sum[0][x] * c % mod;
 52             sum[1][x] = sum[1][x] * c % mod * c % mod;
 53             sum[2][x] = sum[2][x] * c % mod * c % mod * c % mod;
 54         }
 55         else
 56         {
 57             flag[0][x] = 0;
 58             flag[1][x] = 1;
 59             flag[2][x] = c;
 60             sum[0][x] = (tr - tl + 1) * c % mod;
 61             sum[1][x] = (tr - tl + 1) * c % mod * c % mod;
 62             sum[2][x] = (tr - tl + 1) * c % mod * c % mod * c % mod;
 63         }
 64         return;
 65     }
 66     pushdown(x, tl, tr);
 67     if(L <= mid)
 68         update(x << 1, L, R, tl, mid, o, c);
 69     if(mid < R)
 70         update(x << 1 | 1, L, R, mid + 1, tr, o, c);
 71     for(int i = 0; i < 3; ++i)
 72         sum[i][x] = (sum[i][x << 1] + sum[i][x << 1 | 1]) % mod;
 73 }
 74 int query(int x, int L, int R, int tl, int tr, int p)
 75 {
 76     if(L <= tl && tr <= R)
 77         return sum[p][x];
 78     pushdown(x, tl, tr);
 79     int mid = (tl + tr) >> 1, re= 0;
 80     if(L <= mid)
 81         re += query(x << 1, L, R, tl, mid, p);
 82     if(mid < R)
 83         re += query(x << 1 | 1, L, R, mid + 1, tr, p);
 84     return re % mod;
 85 }
 86 int main()
 87 {
 88     while(scanf("%d%d", &n, &m),n)
 89     {
 90         build(1, 1, n);
 91         int o, x, y, c;
 92         while(m--)
 93         {
 94             scanf("%d%d%d%d", &o, &x, &y, &c);
 95             if(o != 4)
 96                 update(1, x, y, 1, n, o - 1, c);
 97             else
 98                 printf("%d\n", query(1, x, y, 1, n, c - 1));
 99         }
100     }
101     return 0;
102 }

 

posted @ 2016-02-06 12:22  sagitta  阅读(213)  评论(0编辑  收藏  举报