算是裸的线段树,不难推出来把所有过程看成 x * a + b ,a、b的值随情况而定。。。把3种下推更新放在同一个公式更新里
#include <cstdio> #include <vector> #include <string> #include <algorithm> #include <queue> #include <cstring> #include <map> #include <set> #include <iostream> #include <cmath> using namespace std; #ifdef __GNUC__ #define LL long long #else #define LL __int64 #endif /* add = x * 1 + b; set = x * 0 + b; multiply = x * c + 0; */ const int MAXN = 100005; const LL MOD = 10007; LL mult[MAXN*3]; // multiply sign; LL add_set[MAXN*3]; // add and set number; LL sum1[MAXN*3], sum2[MAXN*3], sum3[MAXN*3]; #define lson l,m,(cnt<<1) #define rson m+1,r,((cnt<<1)+1) #define mid m=(l+r)>>1 int m, n; void build(int l, int r, int cnt) { add_set[cnt] = 0; mult[cnt] = 1; sum1[cnt] = sum2[cnt] = sum3[cnt] = 0; if (l == r) return; int mid; build(lson); build(rson); } void calcu(int cnt, int mt, int da, int num) { LL d[3], c[3]; d[0] = mt; d[1] = mt*mt%MOD; d[2] = d[1]*mt%MOD; c[0] = da; c[1] = da*da%MOD; c[2] = c[1]*da%MOD; sum3[cnt] = (d[2]*sum3[cnt] + num*c[2] + 3*d[1]*c[0]*sum2[cnt] + 3*d[0]*c[1]*sum1[cnt])%MOD; sum2[cnt] = (d[1]*sum2[cnt] + num*c[1] + 2*d[0]*c[0]*sum1[cnt])%MOD; sum1[cnt] = (d[0]*sum1[cnt] + num*c[0])%MOD; } void pushDown ( int l, int r, int cnt ) { if (mult[cnt] == 1 && add_set[cnt] == 0) return; int mid; int ll = cnt<<1; int rr = ll | 1; mult[ll] = (mult[cnt]*mult[ll])%MOD; add_set[ll] = (add_set[ll]*mult[cnt]+add_set[cnt])%MOD; calcu(ll, mult[cnt], add_set[cnt], m-l+1); mult[rr] = (mult[cnt]*mult[rr])%MOD; add_set[rr] = (add_set[rr]*mult[cnt]+add_set[cnt])%MOD; calcu(rr, mult[cnt], add_set[cnt], r-m); mult[cnt] = 1; add_set[cnt] = 0; } void pushUp(int l, int r, int cnt) { int ll = cnt<<1; int rr = ll | 1; sum1[cnt] = (sum1[ll]+sum1[rr])%MOD; sum2[cnt] = (sum2[ll]+sum2[rr])%MOD; sum3[cnt] = (sum3[ll]+sum3[rr])%MOD; } void madd(int da, int mt, int x, int y, int l, int r, int cnt) { if ( x <= l && y >= r) { mult[cnt] = (mult[cnt]*mt)%MOD; add_set[cnt] = (add_set[cnt]*mt + da)%MOD; calcu(cnt, mt, da, r-l+1); return ; } pushDown(l, r, cnt); int mid; if (x <= m) madd(da, mt, x, y, lson); if (y > m) madd(da, mt, x, y, rson); pushUp(l, r, cnt); } LL mquery(int x, int y, int cc, int l, int r, int cnt) { LL res = 0; if (x <= l && y >= r) { switch(cc) { case 1: return sum1[cnt]; case 2: return sum2[cnt]; case 3: return sum3[cnt]; } } pushDown(l, r, cnt); int mid; if (x <= m) res += mquery(x, y, cc, lson); if (y > m) res += mquery(x, y, cc, rson); return res; } int main() { #ifdef __GNUC__ freopen("in.txt", "r", stdin); #endif while (scanf("%d%d", &n, &m) != EOF && n+m) { build(1, n, 1); while (m--) { int a, x, y, c; scanf("%d%d%d%d", &a, &x, &y, &c); if (a == 1) { madd(c, 1, x, y, 1, n, 1); } else if (a == 2) { madd(0, c, x, y, 1, n, 1); } else if (a == 3) { madd(c, 0, x, y, 1, n, 1); } else { LL res = mquery(x, y, c, 1, n, 1); res %= MOD; printf("%I64d\n", res); } } } return 0; }