异常变态的正常线段树。给你三种操作,三种输出方式:

1.让l~r区间的所有值加c;

2.让l~r区间的所有值乘c;

3.让l~r区间的所有值变成c;

4.让l~r区间的所有值都先求p(1~3)次方,然后求和输出。

别人都是一看题懵逼好简单操作好复杂,我就比较优秀,一看题就懵逼感觉很难不知道怎么做,我对不起这几天努力学的线段树,对不起。其实我考虑到分三种lazy数组,三种ans数组(正常大家都能想到。。。),但是我不知道数组到开2次方,3次方怎么做。再此跟初中老师道歉,大家看下面。

sum1 = a1 + a2 + a3;

sum2 = a1^2 + a2^2 + a3^2;

sum3 = a1^3 + a2^3 + a3^3;

如果每个元素都加c呢?

sum1 = a1 + a2 + a3 + 3*c;

sum2 = (a1 + c)^2 + (a2 + c) ^2 + (a3 + c)^2;

sum3 = (a1 + c)^3 + (a2 + c) ^3 + (a3 + c)^3;

真的傻,我竟然不知道怎么处理sum2,式子分解一下不就好了

sum2 = a1^2 + a2^2 + a3^2 + 2 * c * (a + b + c) + 3 * c^2;

sum2 = 上一状态的sum2 + 2 * c * 上一状态的sum1 + 3 * c^2;

sum3 = .....

每个元素乘c,这个就很简单了,大家都懂,每个元素变成c也很好操作。

这只是其中一种通俗易懂代码写起来不要命的操作,让我写代码不可能的
 

#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF INT_MAX
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = 10007; 
const int maxn = 100000 + 5;
const int N = 12;
LL add[maxn << 2] , set[maxn << 2] , mul[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 build(int l , int r , int rt)
{
    add[rt] = set[rt] = 0;
    mul[rt] = 1;
    if(l == r) {
        sum1[rt] = sum2[rt] = sum3[rt] = 0;
        return;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void PushDown(int rt , int len)
{
    if(set[rt]) {
        set[rt << 1] = set[rt << 1 | 1] = set[rt];
        add[rt << 1] = add[rt << 1 | 1] = 0;    //注意这个也要下放
        mul[rt << 1] = mul[rt << 1 | 1] = 1;
        LL tmp = ((set[rt] * set[rt]) % MOD) * set[rt] % MOD;
        sum1[rt << 1] = ((len - (len >> 1)) % MOD) * (set[rt] % MOD) % MOD;
        sum1[rt << 1 | 1] = ((len >> 1) % MOD) * (set[rt] % MOD) % MOD;
        sum2[rt << 1] = ((len - (len >> 1)) % MOD) * ((set[rt] * set[rt]) % MOD) % MOD;
        sum2[rt << 1 | 1] = ((len >> 1) % MOD) * ((set[rt] * set[rt]) % MOD) % MOD;
        sum3[rt << 1] = ((len - (len >> 1)) % MOD) * tmp % MOD;
        sum3[rt << 1 | 1] = ((len >> 1) % MOD) * tmp % MOD;
        set[rt] = 0;
    }
    if(mul[rt] != 1) {    //这个就是mul[rt] != 1 , 当时我这里没注意所以TLE了
        mul[rt << 1] = (mul[rt << 1] * mul[rt]) % MOD;
        mul[rt << 1 | 1] = (mul[rt << 1 | 1] * mul[rt]) % MOD;
        if(add[rt << 1])    //注意这个也要下放
            add[rt << 1] = (add[rt << 1] * mul[rt]) % MOD;
        if(add[rt << 1 | 1])
            add[rt << 1 | 1] = (add[rt << 1 | 1] * mul[rt]) % MOD;
        LL tmp = (((mul[rt] * mul[rt]) % MOD * 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] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
        sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
        sum3[rt << 1] = (sum3[rt << 1] % MOD) * tmp % MOD;
        sum3[rt << 1 | 1] = (sum3[rt << 1 | 1] % MOD) * tmp % MOD;
        mul[rt] = 1;
    }
    if(add[rt]) {
        add[rt << 1] += add[rt];    //add是+= , mul是*=
        add[rt << 1 | 1] += add[rt];
        LL tmp = (add[rt] * add[rt] % MOD) * add[rt] % MOD;        //注意sum3 , sum2 , sum1的先后顺序
        sum3[rt << 1] = (sum3[rt << 1] + (tmp * (len - (len >> 1)) % MOD) + 3 * add[rt] * ((sum2[rt << 1] + sum1[rt << 1] * add[rt]) % MOD)) % MOD;
        sum3[rt << 1 | 1] = (sum3[rt << 1 | 1] + (tmp * (len >> 1) % MOD) + 3 * add[rt] * ((sum2[rt << 1 | 1] + sum1[rt << 1 | 1] * add[rt]) % MOD)) % MOD;
        sum2[rt << 1] = (sum2[rt << 1] + ((add[rt] * add[rt] % MOD) * (len - (len >> 1)) % MOD) + (2 * sum1[rt << 1] * add[rt] % MOD)) % MOD;
        sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] + (((add[rt] * add[rt] % MOD) * (len >> 1)) % MOD) + (2 * sum1[rt << 1 | 1] * add[rt] % MOD)) % MOD;
        sum1[rt << 1] = (sum1[rt << 1] + (len - (len >> 1)) * add[rt]) % MOD;
        sum1[rt << 1 | 1] = (sum1[rt << 1 | 1] + (len >> 1) * add[rt]) % MOD;
        add[rt] = 0;
    }
}
void update(int L , int R , int c , int ch , int l , int r , int rt)
{
    if(L <= l && R >= r) {
        if(ch == 3) {
            set[rt] = c;
            add[rt] = 0;
            mul[rt] = 1;
            sum1[rt] = ((r - l + 1) * c) % MOD;
            sum2[rt] = ((r - l + 1) * ((c * c) % MOD)) % MOD;
            sum3[rt] = ((r - l + 1) * (((c * c) % MOD) * c % MOD)) % MOD;
        } else if(ch == 2) {
            mul[rt] = (mul[rt] * c) % MOD;
            if(add[rt])
                add[rt] = (add[rt] * c) % MOD;
            sum1[rt] = (sum1[rt] * c) % MOD;
            sum2[rt] = (sum2[rt] * (c * c % MOD)) % MOD;
            sum3[rt] = (sum3[rt] * ((c * c % MOD) * c % MOD)) % MOD;
        } else if(ch == 1) {
            add[rt] += c;
            LL tmp = (((c * c) % MOD * c) % MOD * (r - l + 1)) % MOD;    //(r - l + 1) * c^3
            sum3[rt] = (sum3[rt] + tmp + 3 * c * ((sum2[rt] + sum1[rt] * c) % MOD)) % MOD;
            sum2[rt] = (sum2[rt] + (c * c % MOD * (r - l + 1) % MOD) + 2 * sum1[rt] * c) % MOD;
            sum1[rt] = (sum1[rt] + (r - l + 1) * c) % MOD;
        }
        return;
    }
    PushDown(rt , r - l + 1);
    int m = (l + r) >> 1;
    if(L > m)
        update(L , R , c , ch , rson);
    else if(R <= m)
        update(L , R , c , ch , lson);
    else {
        update(L , R , c , ch , lson);
        update(L , R , c , ch , rson);
    }
    PushUp(rt);
}
LL query(int L , int R , int p , int l , int r , int rt)
{
    if(L <= l && R >= r) {
        if(p == 1)
            return sum1[rt] % MOD;
        else if(p == 2)
            return sum2[rt] % MOD;
        else
            return sum3[rt] % MOD;
    }
    PushDown(rt , r - l + 1);
    int m = (l + r) >> 1;
    if(L > m)
        return query(L , R , p , rson);
    else if(R <= m)
        return query(L , R , p , lson);
    else 
        return (query(L , R , p , lson) + query(L , R , p , rson)) % MOD;
}
int main()
{
    int n , m;
    int a , b , c , ch;
    while(~scanf("%d %d" , &n , &m))
    {
        if(n == 0 && m == 0)
            break;
        build(1 , n , 1);
        while(m--) {
            scanf("%d %d %d %d" , &ch , &a , &b , &c);
            if(ch != 4) {
                update(a , b , c , ch , 1 , n , 1);
            } else {
                printf("%I64d\n" , query(a , b , c , 1 , n , 1));
            }
        }
    }
    return 0;
}

第二种代码就很优秀,把lazy用到极致,我们知道有元素覆盖这种操作(就是把区间内的值全部变成c),如果一个区间的值全一样,那么进行update操作会非常简单,所以你只需要把lazy一直往下传,一直传到区间全相等的时候停止。(当然,时间方面还是很可怕,不过人家ac了,ac就是真理)
 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
 
#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
typedef long long lld;
const int maxn=100005;
const int mod=10007;
lld add[4*maxn], mul[4*maxn], ch[4*maxn], sum[4*maxn];
 
void build(int u, int l, int r)
{
    mul[u]=1;
    add[u]=sum[u]=0;
    ch[u]=0;
    if(l==r)
    {
        ch[u]=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(lz);
    build(rz);
}
 
void push_down(int u, int l, int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(ch[u])
    {
        add[2*u]=0, mul[2*u]=1;
        add[2*u+1]=0, mul[2*u+1]=1;
        ch[2*u]=ch[2*u+1]=1;
        sum[2*u]=sum[2*u+1]=sum[u];
        ch[u]=0;
    }
    else
    {
        if(add[u])
        {
            if(ch[2*u]) sum[2*u]=(sum[2*u]+add[u])%mod;
            else
            {
                push_down(lz);
                add[2*u]=(add[2*u]+add[u])%mod;
            }
            if(ch[2*u+1]) sum[2*u+1]=(sum[2*u+1]+add[u])%mod;
            else
            {
                push_down(rz);
                add[2*u+1]=(add[2*u+1]+add[u])%mod;
            }
            add[u]=0;
        }
        if(mul[u]>1)
        {
            if(ch[2*u]) sum[2*u]=(sum[2*u]*mul[u])%mod;
            else
            {
                push_down(lz);
                mul[2*u]=(mul[2*u]*mul[u])%mod;
            }
            if(ch[2*u+1]) sum[2*u+1]=(sum[2*u+1]*mul[u])%mod;
            else
            {
                push_down(rz);
                mul[2*u+1]=(mul[2*u+1]*mul[u])%mod;
            }
            mul[u]=1;
        }
    }
}
 
void Update(int u, int l, int r, int tl, int tr, int c, int op)
{
    if(tl<=l&&r<=tr)
    {
        if(op==3)
        {
            ch[u]=1;
            mul[u]=1, add[u]=0;
            sum[u]=c;
        }
        else
        {
            if(ch[u])
            {
                if(op==1) sum[u]=(sum[u]+c)%mod;
                else   sum[u]=sum[u]*c%mod;
            }
            else
            {
                push_down(u,l,r);
                if(op==1) add[u]=(add[u]+c)%mod;
                else mul[u]=mul[u]*c%mod;
            }
        }
        return ;
    }
    push_down(u,l,r);
    int mid=(l+r)>>1;
    if(tr<=mid) Update(lz,tl,tr,c,op);
    else if(tl>mid) Update(rz,tl,tr,c,op);
    else
    {
        Update(lz,tl,mid,c,op);
        Update(rz,mid+1,tr,c,op);
    }
}
 
lld Query(int u, int l, int r, int tl, int tr, int p)
{
    if(tl<=l&&r<=tr)
    {
        if(ch[u])
        {
            lld ans=1, tp=sum[u];
            for(int i=1; i<=p; i++) ans=ans*tp%mod;
            return (r-l+1)*ans%mod;
        }
    }
    push_down(u,l,r);
    int mid=(l+r)>>1;
    if(tr<=mid) return Query(lz,tl,tr,p);
    else if(tl>mid) return Query(rz,tl,tr,p);
    else
    {
        lld t1=Query(lz,tl,mid,p);
        lld t2=Query(rz,mid+1,tr,p);
        return (t1+t2)%mod;
    }
}
 
int main()
{
    int n, m;
    while(cin >> n >> m, n+m)
    {
        build(1,1,n);
        for(int i=1; i<=m; i++)
        {
            int l, r, c, op;
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(op<=3) Update(1,1,n,l,r,c,op);
            else printf("%I64d\n",Query(1,1,n,l,r,c)%mod);
        }
    }
    return 0;
}