Transformation

http://acm.hdu.edu.cn/showproblem.php?pid=4578

题意:

含n个数字的的数列a各数字初值均为0,对其进行m次操作,每次操作可为下列之一:

1 x y c:ax到ay间的数字(含边界)均增加c

2 x y c:ax到ay间的数字(含边界)均乘以c

3 x y c:ax到ay间的数字(含边界)均变为c

4 x y p:输出ax到ay间的数字(含边界)的p次方之和

对于每个操作4,输出答案模10007

数据组数<=10。

1<=n,m<=1e5,1<=x<=y<=n,1<=c<=1e4,1<=p<=3

输入 0 0结束

 

解法:

有特意限制p就是水题了

假如p = 1那么显然就是普通的线段树

当p = 2或者p = 3的时候,第2、3种操作依然比较好处理

而对于第一种,我们列个求和公式就能发现更新其实很方便的

线段树里s[i]代表该线段覆覆盖元素的 i 次方之和

更新很简单(自己列求和公式想不出来就参照代码里pushdown函数吧

 

实现:

脑抽了没有线段树没有开s数组而是直接申请了三个变量s1,s2,s3

实际证明完全是给自己找麻烦

手残居然磨磨唧唧写了1h...

还WA了...又改了1h

 

改错:

其实最难的地方在于三个标记的优先顺序

首先有覆盖标记,就下传并把儿子的加法标记和乘法标记改为0和1

其次看乘法标记,乘法标记需要更新儿子的加法标记

最后看加法标记

 

二逼错误:

1.打上覆盖标记后,乘法标记更新为1...乘法标记更新为1不是0!

2.我的ask函数的返回值没有取膜...我可能是脑残吧

  1 #include <cstdio>
  2 
  3 #define lc (o << 1)
  4 #define rc (o << 1 | 1)
  5 
  6 typedef long long ll;
  7 
  8 const int Mod = 10007;
  9 const int maxn = 100010;
 10 
 11 struct node {
 12     ll s1, s2, s3;
 13     ll laza, lazm, lazc;
 14     void clear() {
 15         s1 = s2 = s3 = 0;
 16         laza = lazc = 0;
 17         lazm = 1;
 18     }
 19 }tr[maxn << 2];
 20 
 21 ll z;
 22 int Case, n, m, x, y, op;
 23 
 24 void pushup(int o) {
 25     tr[o].s1 = tr[lc].s1 + tr[rc].s1; 
 26     tr[o].s2 = tr[lc].s2 + tr[rc].s2;
 27     tr[o].s3 = tr[lc].s3 + tr[rc].s3;
 28 }
 29 
 30 void pushdown(int o, int l, int r) {
 31     int mid = (l + r) >> 1;
 32     if(tr[o].lazc) {
 33         tr[lc].s3 = tr[o].lazc * tr[o].lazc * tr[o].lazc * (mid - l + 1)  % Mod;
 34         tr[rc].s3 = tr[o].lazc * tr[o].lazc * tr[o].lazc * (r - mid)  % Mod;
 35         tr[lc].s2 = tr[o].lazc * tr[o].lazc * (mid - l + 1) % Mod; 
 36         tr[rc].s2 = tr[o].lazc * tr[o].lazc * (r - mid) % Mod;
 37         tr[lc].s1 = tr[o].lazc * (mid - l + 1) % Mod; 
 38         tr[rc].s1 = tr[o].lazc * (r - mid) % Mod; 
 39         tr[lc].lazc = tr[rc].lazc = tr[o].lazc;
 40         tr[lc].laza = tr[rc].laza = 0;
 41         tr[lc].lazm = tr[rc].lazm = 1;
 42         tr[o].lazc = 0;    
 43     }
 44     if(tr[o].lazm != 1) {
 45         tr[lc].s3 = (tr[lc].s3 * tr[o].lazm * tr[o].lazm * tr[o].lazm) % Mod;
 46         tr[rc].s3 = (tr[rc].s3 * tr[o].lazm * tr[o].lazm * tr[o].lazm) % Mod;
 47         tr[lc].s2 = (tr[lc].s2 * tr[o].lazm * tr[o].lazm) % Mod;
 48         tr[rc].s2 = (tr[rc].s2 * tr[o].lazm * tr[o].lazm) % Mod;
 49         tr[lc].s1 = (tr[lc].s1 * tr[o].lazm) % Mod;
 50         tr[rc].s1 = (tr[rc].s1 * tr[o].lazm) % Mod;
 51         tr[lc].laza = (tr[lc].laza * tr[o].lazm) % Mod;
 52         tr[rc].laza = (tr[rc].laza * tr[o].lazm) % Mod;
 53         tr[lc].lazm = (tr[lc].lazm * tr[o].lazm) % Mod;
 54         tr[rc].lazm = (tr[rc].lazm * tr[o].lazm) % Mod;
 55         tr[o].lazm = 1;
 56     }
 57     if(tr[o].laza) {
 58         tr[lc].s3 = (tr[lc].s3 + tr[o].laza * tr[lc].s2 * 3 + tr[o].laza * tr[o].laza * tr[lc].s1 * 3 + tr[o].laza * tr[o].laza * tr[o].laza * (mid - l + 1)) % Mod;
 59         tr[rc].s3 = (tr[rc].s3 + tr[o].laza * tr[rc].s2 * 3 + tr[o].laza * tr[o].laza * tr[rc].s1 * 3 + tr[o].laza * tr[o].laza * tr[o].laza * (r - mid)) % Mod;
 60         tr[lc].s2 = (tr[lc].s2 + tr[o].laza * tr[lc].s1 * 2 + tr[o].laza * tr[o].laza * (mid - l + 1)) % Mod;
 61         tr[rc].s2 = (tr[rc].s2 + tr[o].laza * tr[rc].s1 * 2 + tr[o].laza * tr[o].laza * (r - mid)) % Mod;
 62         tr[lc].s1 = (tr[lc].s1 + tr[o].laza * (mid - l + 1)) % Mod;
 63         tr[rc].s1 = (tr[rc].s1 + tr[o].laza * (r - mid)) % Mod;
 64         tr[lc].laza = (tr[lc].laza + tr[o].laza) % Mod;
 65         tr[rc].laza = (tr[rc].laza + tr[o].laza) % Mod;
 66         tr[o].laza = 0;
 67     }
 68 }
 69 
 70 void build(int o, int l, int r) {
 71     tr[o].clear();
 72     if(l == r) return;
 73     int mid = (l + r) >> 1;
 74     build(lc, l, mid);
 75     build(rc, mid + 1, r);
 76 }
 77 
 78 void add(int o, int l, int r) {
 79     if(l != r) pushdown(o, l, r);
 80     if(x <= l && r <= y) {
 81         tr[o].s3 = (tr[o].s3 + z * tr[o].s2 * 3 + z * z * tr[o].s1 * 3 + z * z * z * (r - l + 1)) % Mod;
 82         tr[o].s2 = (tr[o].s2 + z * tr[o].s1 * 2 + z * z * (r - l + 1)) % Mod;
 83         tr[o].s1 = (tr[o].s1 + z * (r - l + 1)) % Mod;
 84         tr[o].laza = (tr[o].laza + z) % Mod;
 85         return;
 86     }
 87     int mid = (l + r) >> 1;
 88     if(x <= mid) add(lc, l, mid);
 89     if(y >  mid) add(rc, mid + 1, r);
 90     pushup(o);
 91 }
 92 
 93 void multiply(int o, int l, int r) {
 94     if(l != r) pushdown(o, l, r);
 95     if(x <= l && r <= y) {
 96         tr[o].s3 = (tr[o].s3 * z * z * z) % Mod;
 97         tr[o].s2 = (tr[o].s2 * z * z) % Mod;
 98         tr[o].s1 = (tr[o].s1 * z) % Mod;
 99         tr[o].lazm = (tr[o].lazm * z) % Mod;
100         return;
101     }
102     int mid = (l + r) >> 1;
103     if(x <= mid) multiply(lc, l, mid);
104     if(y >  mid) multiply(rc, mid + 1, r);
105     pushup(o);
106 }
107 
108 void cover(int o, int l, int r) {
109     if(l != r) pushdown(o, l, r);
110     if(x <= l && r <= y) {
111         tr[o].s3 = z * z * z * (r - l + 1)  % Mod;
112         tr[o].s2 = z * z * (r - l + 1) % Mod; 
113         tr[o].s1 = z * (r - l + 1) % Mod; 
114         tr[o].lazc = z;    
115         return;
116     }
117     int mid = (l + r) >> 1;
118     if(x <= mid) cover(lc, l, mid);
119     if(y >  mid) cover(rc, mid + 1, r);
120     pushup(o);
121 }
122 
123 ll ask(int o, int l, int r) {
124     if(l != r) pushdown(o, l, r);
125     if(x <= l && r <= y) {
126         switch(z) {
127             case 1:return tr[o].s1;
128             case 2:return tr[o].s2;
129             case 3:return tr[o].s3;
130         }
131     }
132     ll res = 0;
133     int mid = (l + r) >> 1;
134     if(x <= mid) res += ask(lc, l, mid);
135     if(y >  mid) res += ask(rc, mid + 1, r);
136     return res % Mod;
137 }
138 
139 int main() {
140     while(scanf("%d %d", &n, &m), n != 0) {
141         build(1, 1, n);
142         while(m --) {
143             scanf("%d %d %d %lld", &op, &x, &y, &z);
144             switch(op) {
145                 case 1:add(1, 1, n);break;
146                 case 2:multiply(1, 1, n);break;
147                 case 3:cover(1, 1, n);break;
148                 case 4:printf("%lld\n", ask(1, 1, n));break;
149             }
150         }
151     }
152     return 0;
153 }
View Code

 

posted @ 2017-03-27 22:57  ztztyyy  阅读(316)  评论(0编辑  收藏  举报