您的位置:首页 > 其它

hdu 4578(区间更新)

2015-08-25 14:15 225 查看
题意:有长度为n的序列,初始都为0,然后有四种操作,1 a b c表示区间[a,b]所有数字加c,2 a b c表示区间[a,b]所有数字都乘c,3 a b c表示区间[a,b]所有数字都设置为c,4 a b p表示输区间[a,b]所有数字的p次方的和,结果模10007。

题解:因为p的取值是1到3,可以开三个线段树分别维护区间内p次方的和,根据(a+c)^2 = a^2+2ac+c^2,(a+c)^3 = a^3+3a^2c+3ac^2+c^3维护平方和和立方和。标记传递因为操作3会覆盖操作1和2,所以操作3要先传递,然后传递操作2,因为操作1的标记addv[k]可以变为addv[k]*c。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int N = 100005;
const int MOD = 10007;
int n, m;
ll tree[N << 2][3], addv[N << 2], mulv[N << 2], setv[N << 2];

void pushup(int k) {
for (int i = 0; i < 3; i++)
tree[k][i] = (tree[k * 2][i] + tree[k * 2 + 1][i]) % MOD;
}

void pushdown(int k, int left, int right) {
int mid = (left + right) / 2;
int lenl = mid - left + 1, lenr = right - mid;
if (setv[k]) {
tree[k * 2][0] = (setv[k] * lenl) % MOD;
tree[k * 2 + 1][0] = (setv[k] * lenr) % MOD;
ll temp = (setv[k] * setv[k]) % MOD;
tree[k * 2][1] = (temp * lenl) % MOD;
tree[k * 2 + 1][1] = (temp * lenr) % MOD;
temp = (temp * setv[k]) % MOD;
tree[k * 2][2] = (temp * lenl) % MOD;
tree[k * 2 + 1][2] = (temp * lenr) % MOD;

setv[k * 2] = setv[k * 2 + 1] = setv[k];
addv[k * 2] = addv[k * 2 + 1] = 0;
mulv[k * 2] = mulv[k * 2 + 1] = 0;
setv[k] = 0;
}
if (mulv[k]) {
for (int i = 0; i < 2; i++)
if (mulv[k * 2 + i])
mulv[k * 2 + i] = (mulv[k * 2 + i] * mulv[k]) % MOD;
else mulv[k * 2 + i] = mulv[k];

addv[k * 2] = (addv[k * 2] * mulv[k]) % MOD;
addv[k * 2 + 1] = (addv[k * 2 + 1] * mulv[k]) % MOD;

tree[k * 2][0] = (tree[k * 2][0] * mulv[k]) % MOD;
tree[k * 2 + 1][0] = (tree[k * 2 + 1][0] * mulv[k]) % MOD;
ll temp = (mulv[k] * mulv[k]) % MOD;
tree[k * 2][1] = (tree[k * 2][1] * temp) % MOD;
tree[k * 2 + 1][1] = (tree[k * 2 + 1][1] * temp) % MOD;
temp = (temp * mulv[k]) % MOD;
tree[k * 2][2] = (tree[k * 2][2] * temp) % MOD;
tree[k * 2 + 1][2] = (tree[k * 2 + 1][2] * temp) % MOD;

mulv[k] = 0;
}
if (addv[k]) {
addv[k * 2] = (addv[k * 2] + addv[k]) % MOD;
addv[k * 2 + 1] = (addv[k * 2 + 1] + addv[k]) % MOD;
ll suml = tree[k * 2][0], sumr = tree[k * 2 + 1][0];
ll suml2 = tree[k * 2][1], sumr2 = tree[k * 2 + 1][1];

tree[k * 2][0] = (tree[k * 2][0] + (addv[k] * lenl) % MOD) % MOD;
tree[k * 2 + 1][0] = (tree[k * 2 + 1][0] + (addv[k] * lenr) % MOD) % MOD;
ll temp = (addv[k] * addv[k]) % MOD;
tree[k * 2][1] = (tree[k * 2][1] + (addv[k] * 2 * suml) % MOD + (temp * lenl) % MOD) % MOD;
tree[k * 2 + 1][1] = (tree[k * 2 + 1][1] + (addv[k] * 2 * sumr) % MOD + (temp * lenr) % MOD) % MOD;
ll temp2 = (temp * addv[k]) % MOD;

tree[k * 2][2] = (tree[k * 2][2] + (temp * 3 * suml) % MOD + (addv[k] * 3 * suml2) % MOD + (temp2 * lenl) % MOD) % MOD;
tree[k * 2 + 1][2] = (tree[k * 2 + 1][2] + (temp * 3 * sumr) % MOD + (addv[k] * 3 * sumr2) % MOD + (temp2 * lenr) % MOD) % MOD;

addv[k] = 0;
}
}

void modify(int k, int left, int right, int l, int r, ll x, int op) {
if (l <= left && right <= r) {
int len = right - left + 1;
if (op == 1) {
addv[k] = (addv[k] + x) % MOD;
ll sum1 = tree[k][0], sum2 = tree[k][1];
tree[k][0] = (tree[k][0] + x * len) % MOD;
ll temp = (x * x) % MOD;
tree[k][1] = (tree[k][1] + (2 * x * sum1) % MOD + (temp * len) % MOD) % MOD;
ll temp2 = (temp * x) % MOD;
tree[k][2] = (tree[k][2] + (3 * temp * sum1) % MOD + (3 * sum2 * x) % MOD + (temp2 * len) % MOD) % MOD;
} else if (op == 2) {
if (mulv[k]) mulv[k] = (mulv[k] * x) % MOD;
else mulv[k] = x;
addv[k] = (addv[k] * x) % MOD;
tree[k][0] = (tree[k][0] * x) % MOD;
ll temp = (x * x) % MOD;
tree[k][1] = (tree[k][1] * temp) % MOD;
temp = (x * temp) % MOD;
tree[k][2] = (tree[k][2] * temp) % MOD;
} else if (op == 3) {
setv[k] = x;
addv[k] = mulv[k] = 0;
tree[k][0] = (x * len) % MOD;
ll temp = (x * x) % MOD;
tree[k][1] = (temp * len) % MOD;
temp = (temp * x) % MOD;
tree[k][2] = (temp * len) % MOD;
}
return;
}
pushdown(k, left, right);
int mid = (left + right) / 2;
if (l <= mid)
modify(k * 2, left, mid, l, r, x, op);
if (r > mid)
modify(k * 2 + 1, mid + 1, right, l, r, x, op);
pushup(k);
return;
}

ll query(int k, int left, int right, int l, int r, int p) {
if (l <= left && right <= r)
return tree[k][p];
pushdown(k, left, right);
int mid = (left + right) / 2;
ll temp = 0;
if (l <= mid)
temp += query(k * 2, left, mid, l, r, p);
if (r > mid)
temp += query(k * 2 + 1, mid + 1, right, l, r, p);
pushup(k);
return temp % MOD;
}

int main() {
while (scanf("%d%d", &n, &m) == 2 && m + n) {
memset(tree, 0, sizeof(tree));
memset(addv, 0, sizeof(addv));
memset(mulv, 0, sizeof(mulv));
memset(setv, 0, sizeof(setv));
int op, l, r;
ll x;
while (m--) {
scanf("%d%d%d%lld", &op, &l, &r, &x);
if (op != 4)
modify(1, 1, n, l, r, x, op);
else
printf("%lld\n", query(1, 1, n, l, r, x - 1));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: