题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578
题目大意:n个数(初始为0)m个操作,操作类型有4种,操作1把区间的每个数+a,操作2把区间的每个数*a.,操作3把区间的每个数=a,操作4,查询区间每个数p次方的和(1<=p<=3)
解:
线段树解决,考虑的问题有两个:
1、赋值操作一定放在前面,然后有 先+后* 和 先*后+ 效果不一样
2、p次方和
对于问题一,采用先*后+的方式,这样在加入一个乘法标记的时候只用给之前的加标记乘上新标记的数即可
对于问题二,把(a+b)^2 和 (a+b)^3 展开,就知道怎么处理了
1 /* 2 * Problem: 3 * Author: SHJWUDP 4 * Created Time: 2015/11/3 星期二 15:20:05 5 * File Name: 1001.cpp 6 * State: 7 * Memo: 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <vector> 12 #include <cstring> 13 #include <algorithm> 14 #include <list> 15 16 using namespace std; 17 18 const int MOD=1e4+7; 19 20 struct SegmentTree { 21 struct Node { 22 vector<long long> sum; 23 vector<long long> delay; 24 Node():sum(3), delay(3){ delay[1]=1; } 25 void relax() { 26 for(auto & x : sum) x%=MOD; 27 for(auto & x : delay) x%=MOD; 28 } 29 }; 30 int n; 31 vector<Node> c; 32 SegmentTree(int _n):n(_n),c(_n<<2){} 33 #define lson l, m, rt<<1 34 #define rson m+1, r, rt<<1|1 35 void deal(Node & o, pair<int, int> p, int range) { 36 auto & d=o.delay; 37 long long b1=p.second, b2=b1*b1, b3=b2*b1; 38 switch(p.first) { 39 case 0: 40 { 41 long long a1=o.sum[0], a2=o.sum[1]; 42 o.sum[2]+=3*a1*b2+3*a2*b1+b3*range; 43 o.sum[1]+=2*a1*b1+b2*range; 44 o.sum[0]+=b1*range; 45 d[0]+=b1; 46 break; 47 } 48 case 1: 49 o.sum[2]*=b3; 50 o.sum[1]*=b2; 51 o.sum[0]*=b1; 52 d[0]*=b1; 53 d[1]*=b1; 54 break; 55 case 2: 56 o.sum[2]=b3*range; 57 o.sum[1]=b2*range; 58 o.sum[0]=b1*range; 59 d[0]=0; d[1]=1; 60 d[2]=b1; 61 break; 62 } 63 o.relax(); 64 } 65 void pushDown(int l, int m, int r, int rt) { 66 for(int i=2; i>=0; --i) { 67 if(!c[rt].delay[i]) continue; 68 if(i==1 && c[rt].delay[i]==1) continue; 69 deal(c[rt<<1], {i, c[rt].delay[i]}, m-l+1); 70 deal(c[rt<<1|1], {i, c[rt].delay[i]}, r-m); 71 } 72 c[rt].delay={0, 1, 0}; 73 } 74 void pushUp(int rt) { 75 for(int i=0; i<3; ++i) { 76 c[rt].sum[i]=(c[rt<<1].sum[i]+c[rt<<1|1].sum[i])%MOD; 77 } 78 } 79 void update(int L, int R, pair<int, int> x, int l, int r, int rt) { 80 if(L<=l && r<=R) { 81 deal(c[rt], x, r-l+1); 82 } else { 83 int m=(l+r)>>1; 84 pushDown(l, m, r, rt); 85 if(L<=m) update(L, R, x, lson); 86 if(m<R) update(L, R, x, rson); 87 pushUp(rt); 88 } 89 } 90 int query(int L, int R, int x, int l, int r, int rt) { 91 if(L<=l && r<=R) { 92 return c[rt].sum[x]; 93 } else { 94 int m=(l+r)>>1; 95 pushDown(l, m, r, rt); 96 int ret=0; 97 if(L<=m) ret=query(L, R, x, lson); 98 if(m<R) ret=(ret+query(L, R, x, rson))%MOD; 99 return ret; 100 } 101 } 102 }; 103 104 int main() { 105 #ifndef ONLINE_JUDGE 106 freopen("in", "r", stdin); 107 freopen("out", "w", stdout); 108 #endif 109 int n, m; 110 while(scanf("%d%d", &n, &m), n||m) { 111 SegmentTree st(n); 112 while(m--) { 113 int op, a, b, c; 114 scanf("%d%d%d%d", &op, &a, &b, &c); 115 --a; --b; 116 // cout<<"<----------------->"<<endl; 117 if(op==4) { 118 printf("%d\n", st.query(a, b, c-1, 0, st.n-1, 1)); 119 } else { 120 st.update(a, b, {op-1, c}, 0, st.n-1, 1); 121 } 122 } 123 } 124 return 0; 125 }