线段树-HDU4578 Transformation
这段区间所有数要加的值。
这段区间所有数要乘的值。
这段区间所有数要变成的值。
这段区间所有数的和、平方和、立方和。
首先我们要规定
现在考虑
#include<bits/stdc++.h>
#include<ctime>
using namespace std;
typedef long long LL;
const LL p = 1e4 + 7;
inline LL read() {
LL x = 0, y = 1; char c = getchar();
while (c > '9' || c < '0') { if (c == '-') y = -1; c = getchar(); }
while (c>='0'&&c<='9') { x=x*10+c-'0';c=getchar(); } return x*y;
}
struct tree
{
LL l, r, Inc, Mul, Fix;
LL s[5];
}t[400050];
void build_tree(LL ni, LL l, LL r)
{
t[ni].l = l; t[ni].r = r;
t[ni].s[1] = t[ni].s[2] = t[ni].s[3] = t[ni].Inc = 0;
t[ni].Fix = -1;
t[ni].Mul = 1;
if (l == r) return;
LL mid = (l + r) >> 1;
build_tree(ni << 1, l, mid);
build_tree((ni << 1) + 1, mid + 1, r);
}
void pd(LL ni)
{
LL ls = (ni << 1), rs = ((ni << 1) + 1);
LL lc = (t[ls].r - t[ls].l + 1), rc = (t[rs].r - t[rs].l + 1);
if (t[ni].Fix != -1)
{
t[ls].Fix = t[rs].Fix = t[ni].Fix;
t[ls].Inc = t[rs].Inc = 0;
t[ls].Mul = t[rs].Mul = 1;
t[ls].s[1] = (t[ls].Fix * lc) % p;
t[ls].s[2] = (t[ls].s[1] * t[ls].Fix) % p;
t[ls].s[3] = (t[ls].s[2] * t[ls].Fix) % p;
t[rs].s[1] = (t[rs].Fix * rc) % p;
t[rs].s[2] = (t[rs].s[1] * t[rs].Fix) % p;
t[rs].s[3] = (t[rs].s[2] * t[rs].Fix) % p;
}
if (t[ni].Mul > 1)
{
LL c1 = t[ni].Mul; LL c2 = (c1 * c1) % p, c3 = (c1 * c1 * c1) % p;
t[ls].Mul = (t[ls].Mul * t[ni].Mul) % p;
t[rs].Mul = (t[rs].Mul * t[ni].Mul) % p;
t[ls].Inc = (t[ls].Inc * t[ni].Mul) % p;
t[rs].Inc = (t[rs].Inc * t[ni].Mul) % p;
LL M = t[ni].Mul; t[ni].Mul = 1;
t[ls].s[1] = (t[ls].s[1] * c1) % p;
t[rs].s[1] = (t[rs].s[1] * c1) % p;
t[ls].s[2] = (t[ls].s[2] * c2) % p;
t[rs].s[2] = (t[rs].s[2] * c2) % p;
t[ls].s[3] = (t[ls].s[3] * c3) % p;
t[rs].s[3] = (t[rs].s[3] * c3) % p;
}
if (t[ni].Inc > 0)
{
t[ls].Inc += t[ni].Inc; t[rs].Inc += t[ni].Inc;
LL c = t[ni].Inc;
t[ls].s[3] = t[ls].s[3] + lc * c * c * c + 3 * t[ls].s[2] * c + 3 * t[ls].s[1] * c * c;
t[ls].s[3] %= p;
t[rs].s[3] = t[rs].s[3] + rc * c * c * c + 3 * t[rs].s[2] * c + 3 * t[rs].s[1] * c * c;
t[rs].s[3] %= p;
t[ls].s[2] = t[ls].s[2] + t[ls].s[1] * c * 2 + lc * c * c;
t[ls].s[2] %= p;
t[rs].s[2] = t[rs].s[2] + t[rs].s[1] * c * 2 + rc * c * c;
t[rs].s[2] %= p;
t[ls].s[1] = (t[ls].s[1] + lc * c) % p;
t[rs].s[1] = (t[rs].s[1] + rc * c) % p;
t[ni].Inc = 0;
}
t[ni].Inc = 0; t[ni].Fix = -1; t[ni].Mul = 1;
}
void pu(LL ni)
{
t[ni].s[1] = (t[ni << 1].s[1] + t[(ni << 1) + 1].s[1]) % p;
t[ni].s[2] = (t[ni << 1].s[2] + t[(ni << 1) + 1].s[2]) % p;
t[ni].s[3] = (t[ni << 1].s[3] + t[(ni << 1) + 1].s[3]) % p;
}
void add(LL ni, LL l, LL r, LL c)
{
if (l <= t[ni].l && t[ni].r <= r)
{
t[ni].Inc = (t[ni].Inc + c) % p;
LL len = t[ni].r - t[ni].l + 1;
t[ni].s[3] = (t[ni].s[3] + 3 * c * t[ni].s[2] + 3 * c * c * t[ni].s[1] + c * c * c * len) % p;
t[ni].s[2] = (t[ni].s[2] + 2 * c * t[ni].s[1] + len * c * c) % p;
t[ni].s[1] = (t[ni].s[1] + c * len) % p;
return;
}
pd(ni);
LL mid = (t[ni].l + t[ni].r) >> 1;
if (l <= mid) add(ni << 1, l, r, c);
if (mid < r) add((ni << 1) + 1, l, r, c);
pu(ni);
}
void mul(LL ni, LL l, LL r, LL c)
{
if (l <= t[ni].l && t[ni].r <= r)
{
t[ni].Inc = (t[ni].Inc * c) % p;
t[ni].Mul = (t[ni].Mul * c) % p;
t[ni].s[3] = (t[ni].s[3] * c * c * c) % p;
t[ni].s[2] = (t[ni].s[2] * c * c) % p;
t[ni].s[1] = (t[ni].s[1] * c) % p;
return;
}
pd(ni);
LL mid = (t[ni].l + t[ni].r) >> 1;
if (l <= mid) mul(ni << 1, l, r, c);
if (mid < r) mul((ni << 1) + 1, l, r, c);
pu(ni);
}
void fix(LL ni, LL l, LL r, LL c)
{
if (l <= t[ni].l && t[ni].r <= r)
{
t[ni].Fix = c;
t[ni].Inc = 0; t[ni].Mul = 1;
LL len = (t[ni].r - t[ni].l + 1);
t[ni].s[1] = (c * len) % p;
t[ni].s[2] = (c * c * len) % p;
t[ni].s[3] = (c * c * c * len) % p;
return;
}
pd(ni);
LL mid = (t[ni].l + t[ni].r) >> 1;
if (l <= mid) fix(ni << 1, l, r, c);
if (mid < r) fix((ni << 1) + 1, l, r, c);
pu(ni);
}
LL que(LL ni, LL l, LL r, LL c)
{
if (l <= t[ni].l && t[ni].r <= r)
{
return t[ni].s[c];
}
pd(ni);
LL mid = (t[ni].l + t[ni].r) >> 1;
LL lr = 0, rr = 0;
if (l <= mid) lr = que(ni << 1, l, r, c);
if (mid < r) rr = que((ni << 1) + 1, l, r, c);
pu(ni);
return (lr + rr) % p;
}
LL n, m;
void main2()
{
build_tree(1, 1, n);
for (LL i = 1; i <= m; ++i)
{
LL o, x, y, z;
o = read(); x = read(); y = read(); z = read();
if (o == 1)
{
add(1, x, y, z);
}
else if (o == 2)
{
mul(1, x, y, z);
}
else if (o == 3)
{
fix(1, x, y, z);
}
else
{
printf("%lld\n", que(1, x, y, z));
}
}
}
LL T;
int main()
{
while (1)
{
n = read(); m = read();
if (!n && !m) break;
main2();
}
return 0;
}