HDU - 4578
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.
题意为n个数,默认为0,有三种操作,一种可以把l到r的每个数+c,其二可以l到r的每个数c,其三可以把l到r每个数变成c。
查询时p=1,输出l到r区间的ai和,p=2时输出l到r区间的ai^2和,p=3输出l到r区间的ai^3和
我们需要保存ai和,ai^2和,ai^3和。三种操作把每个数变成c优先级最高,其二为乘法,最后为加法
需要注意修改时,若为x,则sum1[rt] = sum1[rt] * x, sum2[rt] = sum2[rt] * x * x, sum3[rt] = sum3[rt] * x * x * x,但是若为+x时,(x+y)^2=x^2+2xy+y^2=sum2[rt]+2*y*sum1[rt]+y*y,同理(x+y)^3也可以展开
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 3;
const int mod = 10007;
ll add[maxn << 2], mul[maxn << 2], st[maxn << 2];
ll sum1[maxn << 2], sum2[maxn << 2], sum3[maxn << 2];
void pushup(int rt) {
sum1[rt] = (sum1[rt << 1] + sum1[rt << 1 | 1]) % mod;
sum2[rt] = (sum2[rt << 1] + sum2[rt << 1 | 1]) % mod;
sum3[rt] = (sum3[rt << 1] + sum3[rt << 1 | 1]) % mod;
}
void pushdown(int rt, int l, int r) {
if(st[rt]) {
int mid = l + r >> 1;
sum1[rt << 1] = st[rt] * (mid - l + 1) % mod;
sum1[rt << 1 | 1] = st[rt] * (r - mid) % mod;
sum2[rt << 1] = st[rt] * st[rt] % mod * (mid - l + 1) % mod;
sum2[rt << 1 | 1] = st[rt] * st[rt] % mod * (r - mid) % mod;
sum3[rt << 1] = st[rt] * st[rt] % mod * st[rt] % mod * (mid - l + 1) % mod;
sum3[rt << 1 | 1] = st[rt] * st[rt] % mod * st[rt] % mod * (r - mid) % mod;
st[rt << 1] = st[rt << 1 | 1] = st[rt];
st[rt] = 0;
add[rt << 1] = add[rt << 1 | 1] = 0;
mul[rt << 1] = mul[rt << 1 | 1] = 1;
}
if(mul[rt] != 1) {
mul[rt << 1] = mul[rt << 1] * mul[rt] % mod;
mul[rt << 1 | 1] = mul[rt << 1 | 1] * mul[rt] % mod;
add[rt << 1] = add[rt << 1] * mul[rt] % mod;
add[rt << 1 | 1] = add[rt << 1 | 1] * mul[rt] % mod;
sum1[rt << 1] = sum1[rt << 1] * mul[rt] % mod;
sum1[rt << 1 | 1] = sum1[rt << 1 | 1] * mul[rt] % mod;
sum2[rt << 1] = sum2[rt << 1] * mul[rt] % mod * mul[rt] % mod;
sum2[rt << 1 | 1] = sum2[rt << 1 | 1] * mul[rt] % mod * mul[rt] % mod;
sum3[rt << 1] = sum3[rt << 1] * mul[rt] % mod * mul[rt] % mod * mul[rt] % mod;
sum3[rt << 1 | 1] = sum3[rt << 1 | 1] * mul[rt] % mod * mul[rt] % mod * mul[rt] % mod;
mul[rt] = 1;
}
if(add[rt]) {
add[rt << 1] = add[rt << 1] + add[rt];
add[rt << 1 | 1] = add[rt << 1 | 1] + add[rt];;
int mid = l + r >> 1;
sum3[rt << 1] = (sum3[rt << 1] + 3 * add[rt] % mod * sum2[rt << 1] % mod + 3 * sum1[rt << 1] % mod * add[rt] % mod * add[rt] % mod + add[rt] * add[rt] % mod * add[rt] % mod * (mid - l + 1) % mod) % mod;
sum3[rt << 1 | 1] = (sum3[rt << 1 | 1] + 3 * add[rt] % mod * sum2[rt << 1 | 1] % mod + 3 * sum1[rt << 1 | 1] % mod * add[rt] % mod * add[rt] % mod + add[rt] * add[rt] % mod * add[rt] % mod * (r - mid) % mod) % mod;
sum2[rt << 1] = (sum2[rt << 1] + 2 * add[rt] % mod * sum1[rt << 1] % mod + add[rt] * add[rt] % mod * (mid - l + 1) % mod) % mod;
sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] + 2 * add[rt] % mod * sum1[rt << 1 | 1] % mod + add[rt] * add[rt] % mod * (r - mid) % mod) % mod;
sum1[rt << 1] = (sum1[rt << 1] + (mid - l + 1) * add[rt]) % mod;
sum1[rt << 1 | 1] = (sum1[rt << 1 | 1] + (r - mid) * add[rt]) % mod;
add[rt] = 0;
}
}
void build(int rt, int l, int r) {
sum1[rt] = sum2[rt] = sum3[rt] = 0;
add[rt] = 0;
mul[rt] = 1;
st[rt] = 0;
if(l == r) return;
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
}
void update(int rt, int L, int R, int l, int r, int op, int x) {
if(L <= l && r <= R) {
if(op == 1) {
st[rt] = x;
add[rt] = 0;
mul[rt] = 1;
sum1[rt] = (r - l + 1) * x % mod;
sum2[rt] = (r - l + 1) * x % mod * x % mod;
sum3[rt] = (r - l + 1) * x % mod * x % mod * x % mod;
}
else if(op == 2) {
mul[rt] = mul[rt] * x % mod;
add[rt] = add[rt] * x % mod;
sum1[rt] = sum1[rt] * x % mod;
sum2[rt] = sum2[rt] * x % mod * x % mod;
sum3[rt] = sum3[rt] * x % mod * x % mod * x % mod;
}
else if(op == 3) {
add[rt] = add[rt] + x;
sum3[rt] = (sum3[rt] + 3 * x % mod * sum2[rt] % mod + 3 * sum1[rt] % mod * x % mod * x % mod + x * x % mod * x % mod * (r - l + 1) % mod) % mod;
sum2[rt] = (sum2[rt] + 2 * x % mod * sum1[rt] % mod + x * x % mod * (r - l + 1) % mod) % mod;
sum1[rt] = (sum1[rt] + (r - l + 1) * x) % mod;
}
return;
}
pushdown(rt, l, r);
int mid = l + r >> 1;
if(mid >= R) update(rt << 1, L, R, l, mid, op, x);
else if(mid < L) update(rt << 1 | 1, L, R, mid + 1, r, op, x);
else update(rt << 1, L, R, l, mid, op, x), update(rt << 1 | 1, L, R, mid + 1, r, op, x);
pushup(rt);
}
ll query(int rt, int L, int R, int l, int r, int p) {
if(L <= l && r <= R) {
if(p == 1) return sum1[rt] % mod;
else if(p == 2) return sum2[rt] % mod;
else if(p == 3) return sum3[rt] % mod;
}
pushdown(rt, l, r);
int mid = l + r >> 1;
if(mid >= R) return query(rt << 1, L, R, l, mid, p);
else if(mid < L) return query(rt << 1 | 1, L, R, mid + 1, r, p);
else return (query(rt << 1, L, R, l, mid, p) + query(rt << 1 | 1, L, R, mid + 1, r, p)) % mod;
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m)) {
if(n == 0 && m == 0) break;
build(1, 1, n);
while(m--) {
int x, l, r, p;
scanf("%d%d%d%d", &x, &l, &r, &p);
if(x == 1) update(1, l, r, 1, n, 3, p);
else if(x == 2) update(1, l, r, 1, n, 2, p);
else if(x == 3) update(1, l, r, 1, n, 1, p);
else printf("%lld\n", query(1, l, r, 1, n, p));
}
}
}