hdu 4578 Transformation 线段树
Posted iat14
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4578 Transformation 线段树相关的知识,希望对你有一定的参考价值。
区间加,区间乘,区间修改,区间1到3次方和查询。
(x + a)^2 = x^2 + ax + a^2
(x + a)^3 = x^3 + a^2x + ax^2 + a^3
所以我们发现3次方和再涉及到加法修改时,可以由2次方和推出。2次方和涉及到加法修改时,可以由一次方和推出。
乘法修改更简单,直接乘上对应次数的a即可。
而修改值也很简单,直接改成新值的对应平方和即可。
lzy标记是,修改值最高,乘法优先度其次,加法次之。
修改值lzy下传时,直接删除掉其他的lzy即可,并维护新的修改值lzy即可。跟19年上海的题好像啊。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 #define int long long 7 int sum[4][810000],lzy[3][810000],vec[210000]; 8 int n,m; 9 const int mo = 10007; 10 void up(int k) 11 { 12 for (int i = 1;i <= 3;i++) 13 sum[i][k] = (sum[i][k << 1] + sum[i][k << 1 | 1]) % mo; 14 } 15 void build(int k,int l,int r) 16 { 17 lzy[0][k] = 0; 18 lzy[1][k] = 0; 19 lzy[2][k] = 1; 20 if (l == r) 21 { 22 sum[1][k] = vec[l] % mo; 23 sum[2][k] = sum[1][k] * vec[l] % mo; 24 sum[3][k] = sum[2][k] * vec[l] % mo; 25 return; 26 } 27 int mid = l + r >> 1; 28 build(k << 1,l,mid); 29 build(k << 1 | 1,mid + 1,r); 30 up(k); 31 } 32 void down(int k,int l,int r) 33 { 34 if (l == r) 35 { 36 lzy[2][k] = 1; 37 lzy[1][k] = 0; 38 lzy[0][k] = 0; 39 return; 40 } 41 int mid = l + r >> 1; 42 if (lzy[0][k] != 0) 43 { 44 sum[1][k << 1] = (mid - l + 1) % mo * lzy[0][k] % mo; 45 sum[1][k << 1 | 1] = (r - mid) % mo * lzy[0][k] % mo; 46 sum[2][k << 1] = sum[1][k << 1] * lzy[0][k] % mo; 47 sum[2][k << 1 | 1] = sum[1][k << 1 | 1] * lzy[0][k] % mo; 48 sum[3][k << 1] = sum[2][k << 1] * lzy[0][k] % mo; 49 sum[3][k << 1 | 1] = sum[2][k << 1 | 1] * lzy[0][k] % mo; 50 lzy[0][k << 1] = lzy[0][k << 1 | 1] = lzy[0][k]; 51 lzy[1][k << 1] = lzy[1][k << 1 | 1] = 0; 52 lzy[2][k << 1] = lzy[2][k << 1 | 1] = 1; 53 lzy[0][k] = 0; 54 } 55 if (lzy[2][k] != 1) 56 { 57 sum[1][k << 1] = sum[1][k << 1] * lzy[2][k] % mo; 58 sum[2][k << 1] = sum[2][k << 1] * lzy[2][k] % mo * lzy[2][k] % mo; 59 sum[3][k << 1] = sum[3][k << 1] * lzy[2][k] % mo * lzy[2][k] % mo * lzy[2][k] % mo; 60 sum[1][k << 1 | 1] = sum[1][k << 1 | 1] * lzy[2][k] % mo; 61 sum[2][k << 1 | 1] = sum[2][k << 1 | 1] * lzy[2][k] % mo * lzy[2][k] % mo; 62 sum[3][k << 1 | 1] = sum[3][k << 1 | 1] * lzy[2][k] % mo * lzy[2][k] % mo * lzy[2][k] % mo; 63 lzy[2][k << 1] = lzy[2][k << 1] * lzy[2][k] % mo; 64 lzy[2][k << 1 | 1] = lzy[2][k << 1 | 1] * lzy[2][k] % mo; 65 lzy[1][k << 1] = lzy[1][k << 1] * lzy[2][k] % mo; 66 lzy[1][k << 1 | 1] = lzy[1][k << 1 | 1] * lzy[2][k] % mo; 67 lzy[2][k] = 1; 68 } 69 if (lzy[1][k] != 0) 70 { 71 sum[3][k << 1] = ((((sum[3][k << 1] + sum[2][k << 1] * lzy[1][k] % mo * 3 % mo) % mo + sum[1][k << 1] * lzy[1][k] % mo * lzy[1][k] % mo * 3 % mo) % mo) + lzy[1][k] * lzy[1][k] % mo * lzy[1][k] % mo * (mid - l + 1) % mo) % mo; 72 sum[2][k << 1] = ((sum[2][k << 1] + lzy[1][k] * lzy[1][k] % mo * (mid - l + 1) % mo) % mo + lzy[1][k] * sum[1][k << 1] % mo * 2 % mo) % mo; 73 sum[1][k << 1] = (sum[1][k << 1] + lzy[1][k] * (mid - l + 1) % mo) % mo; 74 sum[3][k << 1 | 1] = ((((sum[3][k << 1 | 1] + sum[2][k << 1 | 1] * lzy[1][k] % mo * 3 % mo) % mo + sum[1][k << 1 | 1] * lzy[1][k] % mo * lzy[1][k] % mo * 3 % mo) % mo) + lzy[1][k] * lzy[1][k] % mo * lzy[1][k] % mo * (r - mid) % mo) % mo; 75 sum[2][k << 1 | 1] = ((sum[2][k << 1 | 1] + lzy[1][k] * lzy[1][k] % mo * (r - mid) % mo) % mo + lzy[1][k] * sum[1][k << 1 | 1] % mo * 2 % mo) % mo; 76 sum[1][k << 1 | 1] = (sum[1][k << 1 | 1] + lzy[1][k] * (r - mid) % mo) % mo; 77 lzy[1][k << 1] = (lzy[1][k << 1] + lzy[1][k]) % mo; 78 lzy[1][k << 1 | 1] = (lzy[1][k << 1 | 1] + lzy[1][k]) % mo; 79 lzy[1][k] = 0; 80 } 81 } 82 83 int query(int k,int l,int r,int x,int y,int v) 84 { 85 if (x <= l && r <= y) 86 return sum[v][k]; 87 down(k,l,r); 88 int mid = l + r >> 1,res = 0; 89 if (x <= mid) 90 res = (res + query(k << 1,l,mid,x,y,v)) % mo; 91 if (y >= mid + 1) 92 res = (res + query(k << 1 | 1,mid + 1,r,x,y,v)) % mo; 93 up(k); 94 return res; 95 } 96 void add(int k,int l,int r,int x,int y,int ad) 97 { 98 down(k,l,r); 99 if (x <= l && r <= y) 100 { 101 sum[3][k] = ((((sum[3][k] + sum[2][k] * ad % mo * 3 % mo) % mo + sum[1][k] * ad % mo * ad % mo * 3 % mo) % mo) + ad * ad % mo * ad % mo * (r - l + 1) % mo) % mo; 102 sum[2][k] = ((sum[2][k] + ad * ad % mo * (r - l + 1) % mo) % mo + ad * sum[1][k] % mo * 2 % mo) % mo; 103 sum[1][k] = (sum[1][k] + ad * (r - l + 1) % mo) % mo; 104 lzy[1][k] = (lzy[1][k] + ad) % mo; 105 return; 106 } 107 int mid = l + r >> 1; 108 if (x <= mid) 109 add(k << 1,l,mid,x,y,ad); 110 if (y >= mid + 1) 111 add(k << 1 | 1,mid + 1,r,x,y,ad); 112 up(k); 113 } 114 void mul(int k,int l,int r,int x,int y,int mu) 115 { 116 down(k,l,r); 117 if (x <= l && r <= y) 118 { 119 sum[1][k] = sum[1][k] * mu % mo; 120 sum[2][k] = sum[2][k] * mu % mo * mu % mo; 121 sum[3][k] = sum[3][k] * mu % mo * mu % mo * mu % mo; 122 lzy[2][k] = lzy[2][k] * mu % mo; 123 return; 124 } 125 int mid = l + r >> 1; 126 if (x <= mid) 127 mul(k << 1,l,mid,x,y,mu); 128 if (y >= mid + 1) 129 mul(k << 1 | 1,mid + 1,r,x,y,mu); 130 up(k); 131 } 132 void chg(int k,int l,int r,int x,int y,int c) 133 { 134 down(k,l,r); 135 if (x <= l && r <= y) 136 { 137 sum[1][k] = (r - l + 1) % mo * c % mo; 138 sum[2][k] = sum[1][k] * c % mo; 139 sum[3][k] = sum[2][k] * c % mo; 140 lzy[0][k] = c; 141 return; 142 } 143 int mid = l + r >> 1; 144 if (x <= mid) 145 chg(k << 1,l,mid,x,y,c); 146 if (y >= mid + 1) 147 chg(k << 1 | 1,mid + 1,r,x,y,c); 148 up(k); 149 } 150 main() 151 { 152 while (scanf("%lld%lld",&n,&m) > 0 && n) 153 { 154 for (int i = 1;i <= n;i++) 155 vec[i] = 0; 156 build(1,1,n); 157 int opt,tl,tr,tv; 158 for (int i = 1;i <= m;i++) 159 { 160 scanf("%lld",&opt); 161 if (opt == 1) 162 { 163 scanf("%lld%lld%lld",&tl,&tr,&tv); 164 add(1,1,n,tl,tr,tv % mo); 165 }else if (opt == 2) 166 { 167 scanf("%lld%lld%lld",&tl,&tr,&tv); 168 mul(1,1,n,tl,tr,tv % mo); 169 }else if (opt == 3) 170 { 171 scanf("%lld%lld%lld",&tl,&tr,&tv); 172 chg(1,1,n,tl,tr,tv % mo); 173 }else 174 { 175 scanf("%lld%lld%lld",&tl,&tr,&tv); 176 printf("%lld ",query(1,1,n,tl,tr,tv)); 177 } 178 } 179 } 180 return 0; 181 }
以上是关于hdu 4578 Transformation 线段树的主要内容,如果未能解决你的问题,请参考以下文章
30-Transformation(HDU4578)-区间线段树(复杂)