本来是很裸的线段树,但是如果用lazy操作,情况太多了,很烦躁。需要考虑先加后乘和先乘后加的不同处理。
更新sum值时,考虑对一个区间内的数加上一个数c后对这三个值有什么影响。首先考虑一个数c的情况。一次方就不说了直接加上c*区间长度len就行了。
二次方。一个数开始为a。后来为a+c。则平方后为a*a+2*a*c+c*c。比原来多了2*a*c+c*c。而对于整个区间增加
2*sum[1]*c+len*c*c。三次方增加3*sum[2]*c+3*sum[1]*c*c+len*c*c*c。
代码写的恶心死了.................
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 100050
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
# define mod 10007
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std;
struct node {
int r,l,mid;
int lazy1,lazy2;
int sum[4];
} tr[4*MAX];
int n,m;
void up(int num) {
for(int i=1; i<=3; i++) tr[num].sum[i] = (tr[L(num)].sum[i] + tr[R(num)].sum[i]) % mod;
}
int cal2(int x) {
return x * x % mod;
}
int cal3(int x) {
return cal2(x) * x % mod;
}
void build(int l,int r,int num) {
tr[num].l = l;
tr[num].r = r;
tr[num].mid = (l+r) >> 1;
tr[num].lazy1 = 0;
tr[num].lazy2 = 1;
if(l == r) {
for(int i=1; i<=3; i++) tr[num].sum[i] = 0;
return ;
}
build(l,tr[num].mid,L(num));
build(tr[num].mid+1,r,R(num));
up(num);
//
}
void down(int num) {
if(tr[num].lazy2 != 1) {
tr[L(num)].lazy2 = tr[L(num)].lazy2 * tr[num].lazy2 % mod;
tr[L(num)].lazy1 = tr[L(num)].lazy1 * tr[num].lazy2 % mod;
tr[R(num)].lazy2 = tr[R(num)].lazy2 * tr[num].lazy2 % mod;
tr[R(num)].lazy1 = tr[R(num)].lazy1 * tr[num].lazy2 % mod;
tr[L(num)].sum[1] = tr[L(num)].sum[1] * tr[num].lazy2 % mod;
tr[R(num)].sum[1] = tr[R(num)].sum[1] * tr[num].lazy2 % mod;
tr[L(num)].sum[2] = tr[L(num)].sum[2] * cal2(tr[num].lazy2) % mod;
tr[R(num)].sum[2] = tr[R(num)].sum[2] * cal2(tr[num].lazy2) % mod;
tr[L(num)].sum[3] = tr[L(num)].sum[3] * cal3(tr[num].lazy2) % mod;
tr[R(num)].sum[3] = tr[R(num)].sum[3] * cal3(tr[num].lazy2) % mod;
tr[num].lazy2 = 1;
}
if(tr[num].lazy1 != 0) {
tr[L(num)].lazy1 = tr[L(num)].lazy1 + tr[num].lazy1 % mod;
tr[R(num)].lazy1 = tr[R(num)].lazy1 + tr[num].lazy1 % mod;
int lenl = tr[L(num)].r - tr[L(num)].l + 1;
int lenr = tr[R(num)].r - tr[R(num)].l + 1;
tr[L(num)].sum[3] = (tr[L(num)].sum[3] + cal3(tr[num].lazy1) * lenl % mod) % mod;
tr[R(num)].sum[3] = (tr[R(num)].sum[3] + cal3(tr[num].lazy1) * lenr % mod) % mod;
tr[L(num)].sum[3] = (tr[L(num)].sum[3] + 3 * tr[L(num)].sum[1] % mod * cal2(tr[num].lazy1) % mod) % mod;
tr[R(num)].sum[3] = (tr[R(num)].sum[3] + 3 * tr[R(num)].sum[1] % mod * cal2(tr[num].lazy1) % mod) % mod;
tr[L(num)].sum[3] = (tr[L(num)].sum[3] + 3 * tr[L(num)].sum[2] % mod * tr[num].lazy1 % mod) % mod;
tr[R(num)].sum[3] = (tr[R(num)].sum[3] + 3 * tr[R(num)].sum[2] % mod * tr[num].lazy1 % mod) % mod;
tr[L(num)].sum[2] = (tr[L(num)].sum[2] + cal2(tr[num].lazy1) * lenl % mod) % mod;
tr[R(num)].sum[2] = (tr[R(num)].sum[2] + cal2(tr[num].lazy1) * lenr % mod) % mod;
tr[L(num)].sum[2] = (tr[L(num)].sum[2] + 2 * tr[L(num)].sum[1] % mod * tr[num].lazy1 % mod) % mod;
tr[R(num)].sum[2] = (tr[R(num)].sum[2] + 2 * tr[R(num)].sum[1] % mod * tr[num].lazy1 % mod) % mod;
tr[L(num)].sum[1] = (tr[L(num)].sum[1] + tr[num].lazy1 * lenl % mod) % mod;
tr[R(num)].sum[1] = (tr[R(num)].sum[1] + tr[num].lazy1 * lenr % mod) % mod;
tr[num].lazy1 = 0;
}
}
void update(int l,int r,int num,int k1,int k2) {
if(l == tr[num].l && r == tr[num].r) {
if(k2 != 1) {
tr[num].lazy2 = tr[num].lazy2 * k2 % mod;
tr[num].lazy1 = k2 * tr[num].lazy1 % mod;
tr[num].sum[3] = tr[num].sum[3] * cal3(k2) % mod;
tr[num].sum[2] = tr[num].sum[2] * cal2(k2) % mod;
tr[num].sum[1] = tr[num].sum[1] * k2 % mod;
}
if(k1 != 0) {
int len = tr[num].r - tr[num].l + 1;
tr[num].lazy1 = k1 + tr[num].lazy1 % mod;
tr[num].sum[3] = (tr[num].sum[3] + cal3(k1) * len % mod) % mod;
tr[num].sum[3] = (tr[num].sum[3] + 3 * tr[num].sum[1] % mod * cal2(k1) % mod) % mod;
tr[num].sum[3] = (tr[num].sum[3] + 3 * tr[num].sum[2] % mod * k1 % mod) % mod;
tr[num].sum[2] = (tr[num].sum[2] + cal2(k1) * len % mod) % mod;
tr[num].sum[2] = (tr[num].sum[2] + 2 * tr[num].sum[1] % mod * k1 % mod) % mod;
tr[num].sum[1] = (tr[num].sum[1] + k1 * len % mod) % mod;
}
return ;
}
down(num);
if(r <= tr[num].mid) {
update(l,r,L(num),k1,k2);
} else if(l > tr[num].mid) {
update(l,r,R(num),k1,k2);
} else {
update(l,tr[num].mid,L(num),k1,k2);
update(tr[num].mid + 1,r,R(num),k1,k2);
}
up(num);
}
int query(int l,int r,int num,int p) {
if(l == tr[num].l && r == tr[num].r) {
return tr[num].sum[p] % mod;
}
down(num);
if(r <= tr[num].mid) {
return query(l,r,L(num), p);
} else if(l > tr[num].mid) {
return query(l,r,R(num), p);
} else {
return (query(l,tr[num].mid,L(num),p) + query(tr[num].mid + 1,r,R(num),p)) % mod;
}
}
void test(int n) {
for(int i=1; i<=3*n; i++) {
printf("l:%d r:%d sum:%d lazy1:%d lazy2:%d\n",tr[i].l,tr[i].r,tr[i].sum[3],tr[i].lazy1,tr[i].lazy2);
}
}
int main() {
int x,y,c,p;
while(cin >> n >> m) {
if(n == 0 && m == 0) break;
build(1,n,1);
for(int i=0; i<m; i++) {
scanf("%d%d%d%d",&p,&x,&y,&c);
if(p == 1) {
update(x,y,1,c,1);
}
if(p == 2) {
update(x,y,1,0,c);
}
if(p == 3) {
update(x,y,1,c,0);
}
if(p == 4) {
printf("%d\n",query(x,y,1,c));
}
}
}
return 0;
}