Transformation
Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)
Total Submission(s): 49 Accepted Submission(s): 16
Problem Description
Yuanfang is puzzled with the question below:
There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
Input
There are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
Sample Input
5 5 3 3 5 7 1 2 4 4 4 1 5 2 2 2 5 8 4 3 5 3 0 0
Sample Output
307 7489
Source
很裸的線段樹的題目。
但是做起來比較麻煩。
我用sum1,sum2,sum3分別代表和、平方和、立方和。
懶惰標記使用三個變量:
lazy1:是加的數
lazy2:是乘的倍數
lazy3:是賦值為一個常數,為0表示沒有。
更新操作需要注意很多細節。
1 /* ********************************************** 2 Author : kuangbin 3 Created Time: 2013/8/10 13:24:03 4 File Name : F:\2013ACM練習\比賽練習\2013杭州邀請賽重現\1003.cpp 5 *********************************************** */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 using namespace std; 19 const int MOD = 10007; 20 const int MAXN = 100010; 21 struct Node 22 { 23 int l,r; 24 int sum1,sum2,sum3; 25 int lazy1,lazy2,lazy3; 26 }segTree[MAXN*3]; 27 void build(int i,int l,int r) 28 { 29 segTree[i].l = l; 30 segTree[i].r = r; 31 segTree[i].sum1 = segTree[i].sum2 = segTree[i].sum3 = 0; 32 segTree[i].lazy1 = segTree[i].lazy3 = 0; 33 segTree[i].lazy2 = 1; 34 int mid = (l+r)/2; 35 if(l == r)return; 36 build(i<<1,l,mid); 37 build((i<<1)|1,mid+1,r); 38 } 39 void push_up(int i) 40 { 41 if(segTree[i].l == segTree[i].r) 42 return; 43 segTree[i].sum1 = (segTree[i<<1].sum1 + segTree[(i<<1)|1].sum1)%MOD; 44 segTree[i].sum2 = (segTree[i<<1].sum2 + segTree[(i<<1)|1].sum2)%MOD; 45 segTree[i].sum3 = (segTree[i<<1].sum3 + segTree[(i<<1)|1].sum3)%MOD; 46 47 } 48 49 void push_down(int i) 50 { 51 if(segTree[i].l == segTree[i].r) return; 52 if(segTree[i].lazy3 != 0) 53 { 54 segTree[i<<1].lazy3 = segTree[(i<<1)|1].lazy3 = segTree[i].lazy3; 55 segTree[i<<1].lazy1 = segTree[(i<<1)|1].lazy1 = 0; 56 segTree[i<<1].lazy2 = segTree[(i<<1)|1].lazy2 = 1; 57 segTree[i<<1].sum1 = (segTree[i<<1].r - segTree[i<<1].l + 1)*segTree[i<<1].lazy3%MOD; 58 segTree[i<<1].sum2 = (segTree[i<<1].r - segTree[i<<1].l + 1)*segTree[i<<1].lazy3%MOD*segTree[i<<1].lazy3%MOD; 59 segTree[i<<1].sum3 = (segTree[i<<1].r - segTree[i<<1].l + 1)*segTree[i<<1].lazy3%MOD*segTree[i<<1].lazy3%MOD*segTree[i<<1].lazy3%MOD; 60 segTree[(i<<1)|1].sum1 = (segTree[(i<<1)|1].r - segTree[(i<<1)|1].l + 1)*segTree[(i<<1)|1].lazy3%MOD; 61 segTree[(i<<1)|1].sum2 = (segTree[(i<<1)|1].r - segTree[(i<<1)|1].l + 1)*segTree[(i<<1)|1].lazy3%MOD*segTree[(i<<1)|1].lazy3%MOD; 62 segTree[(i<<1)|1].sum3 = (segTree[(i<<1)|1].r - segTree[(i<<1)|1].l + 1)*segTree[(i<<1)|1].lazy3%MOD*segTree[(i<<1)|1].lazy3%MOD*segTree[(i<<1)|1].lazy3%MOD; 63 segTree[i].lazy3 = 0; 64 } 65 if(segTree[i].lazy1 != 0 || segTree[i].lazy2 != 1) 66 { 67 segTree[i<<1].lazy1 = ( segTree[i].lazy2*segTree[i<<1].lazy1%MOD + segTree[i].lazy1 )%MOD; 68 segTree[i<<1].lazy2 = segTree[i<<1].lazy2*segTree[i].lazy2%MOD; 69 int sum1,sum2,sum3; 70 sum1 = (segTree[i<<1].sum1*segTree[i].lazy2%MOD + (segTree[i<<1].r - segTree[i<<1].l + 1)*segTree[i].lazy1%MOD)%MOD; 71 sum2 = (segTree[i].lazy2 * segTree[i].lazy2 % MOD * segTree[i<<1].sum2 % MOD + 2*segTree[i].lazy1*segTree[i].lazy2%MOD * segTree[i<<1].sum1%MOD + (segTree[i<<1].r - segTree[i<<1].l + 1)*segTree[i].lazy1%MOD*segTree[i].lazy1%MOD)%MOD; 72 sum3 = segTree[i].lazy2 * segTree[i].lazy2 % MOD * segTree[i].lazy2 % MOD * segTree[i<<1].sum3 % MOD; 73 sum3 = (sum3 + 3*segTree[i].lazy2 % MOD * segTree[i].lazy2 % MOD * segTree[i].lazy1 % MOD * segTree[i<<1].sum2) % MOD; 74 sum3 = (sum3 + 3*segTree[i].lazy2 % MOD * segTree[i].lazy1 % MOD * segTree[i].lazy1 % MOD * segTree[i<<1].sum1) % MOD; 75 sum3 = (sum3 + (segTree[i<<1].r - segTree[i<<1].l + 1)*segTree[i].lazy1%MOD * segTree[i].lazy1 % MOD * segTree[i].lazy1 % MOD) % MOD; 76 segTree[i<<1].sum1 = sum1; 77 segTree[i<<1].sum2 = sum2; 78 segTree[i<<1].sum3 = sum3; 79 segTree[(i<<1)|1].lazy1 = ( segTree[i].lazy2*segTree[(i<<1)|1].lazy1%MOD + segTree[i].lazy1 )%MOD; 80 segTree[(i<<1)|1].lazy2 = segTree[(i<<1)|1].lazy2 * segTree[i].lazy2 % MOD; 81 sum1 = (segTree[(i<<1)|1].sum1*segTree[i].lazy2%MOD + (segTree[(i<<1)|1].r - segTree[(i<<1)|1].l + 1)*segTree[i].lazy1%MOD)%MOD; 82 sum2 = (segTree[i].lazy2 * segTree[i].lazy2 % MOD * segTree[(i<<1)|1].sum2 % MOD + 2*segTree[i].lazy1*segTree[i].lazy2%MOD * segTree[(i<<1)|1].sum1%MOD + (segTree[(i<<1)|1].r - segTree[(i<<1)|1].l + 1)*segTree[i].lazy1%MOD*segTree[i].lazy1%MOD)%MOD; 83 sum3 = segTree[i].lazy2 * segTree[i].lazy2 % MOD * segTree[i].lazy2 % MOD * segTree[(i<<1)|1].sum3 % MOD; 84 sum3 = (sum3 + 3*segTree[i].lazy2 % MOD * segTree[i].lazy2 % MOD * segTree[i].lazy1 % MOD * segTree[(i<<1)|1].sum2) % MOD; 85 sum3 = (sum3 + 3*segTree[i].lazy2 % MOD * segTree[i].lazy1 % MOD * segTree[i].lazy1 % MOD * segTree[(i<<1)|1].sum1) % MOD; 86 sum3 = (sum3 + (segTree[(i<<1)|1].r - segTree[(i<<1)|1].l + 1)*segTree[i].lazy1%MOD * segTree[i].lazy1 % MOD * segTree[i].lazy1 % MOD) % MOD; 87 segTree[(i<<1)|1].sum1 = sum1; 88 segTree[(i<<1)|1].sum2 = sum2; 89 segTree[(i<<1)|1].sum3 = sum3; 90 segTree[i].lazy1 = 0; 91 segTree[i].lazy2 = 1; 92 93 } 94 } 95 void update(int i,int l,int r,int type,int c) 96 { 97 if(segTree[i].l == l && segTree[i].r == r) 98 { 99 c %= MOD; 100 if(type == 1) 101 { 102 segTree[i].lazy1 += c; 103 segTree[i].lazy1 %= MOD; 104 segTree[i].sum3 = (segTree[i].sum3 + 3*segTree[i].sum2%MOD*c%MOD + 3*segTree[i].sum1%MOD*c%MOD*c%MOD + (segTree[i].r - segTree[i].l + 1)*c%MOD*c%MOD*c%MOD)%MOD; 105 segTree[i].sum2 = (segTree[i].sum2 + 2*segTree[i].sum1%MOD*c%MOD + (segTree[i].r - segTree[i].l + 1)*c%MOD*c%MOD)%MOD; 106 segTree[i].sum1 = (segTree[i].sum1 + (segTree[i].r - segTree[i].l + 1)*c%MOD)%MOD; 107 } 108 else if(type == 2) 109 { 110 segTree[i].lazy1 = segTree[i].lazy1*c%MOD; 111 segTree[i].lazy2 = segTree[i].lazy2*c%MOD; 112 segTree[i].sum1 = segTree[i].sum1*c%MOD; 113 segTree[i].sum2 = segTree[i].sum2*c%MOD*c%MOD; 114 segTree[i].sum3 = segTree[i].sum3*c%MOD*c%MOD*c%MOD; 115 } 116 else 117 { 118 segTree[i].lazy1 = 0; 119 segTree[i].lazy2 = 1; 120 segTree[i].lazy3 = c%MOD; 121 segTree[i].sum1 = c*(segTree[i].r - segTree[i].l + 1)%MOD; 122 segTree[i].sum2 = c*(segTree[i].r - segTree[i].l + 1)%MOD*c%MOD; 123 segTree[i].sum3 = c*(segTree[i].r - segTree[i].l + 1)%MOD*c%MOD*c%MOD; 124 } 125 return; 126 } 127 push_down(i); 128 int mid = (segTree[i].l + segTree[i].r)/2; 129 if(r <= mid)update(i<<1,l,r,type,c); 130 else if(l > mid)update((i<<1)|1,l,r,type,c); 131 else 132 { 133 update(i<<1,l,mid,type,c); 134 update((i<<1)|1,mid+1,r,type,c); 135 } 136 push_up(i); 137 } 138 int query(int i,int l,int r,int p) 139 { 140 if(segTree[i].l == l && segTree[i].r == r) 141 { 142 if(p == 1)return segTree[i].sum1; 143 else if(p== 2)return segTree[i].sum2; 144 else return segTree[i].sum3; 145 } 146 push_down(i); 147 int mid = (segTree[i].l + segTree[i].r )/2; 148 if(r <= mid)return query(i<<1,l,r,p); 149 else if(l > mid)return query((i<<1)|1,l,r,p); 150 else return (query(i<<1,l,mid,p)+query((i<<1)|1,mid+1,r,p))%MOD; 151 } 152 153 int main() 154 { 155 //freopen("in.txt","r",stdin); 156 //freopen("out.txt","w",stdout); 157 int n,m; 158 while(scanf("%d%d",&n,&m) == 2) 159 { 160 if(n == 0 && m == 0)break; 161 build(1,1,n); 162 int type,x,y,c; 163 while(m--) 164 { 165 scanf("%d%d%d%d",&type,&x,&y,&c); 166 if(type == 4)printf("%d\n",query(1,x,y,c)); 167 else update(1,x,y,type,c); 168 } 169 } 170 return 0; 171 }