直接贴代码吧:
这题码量挺大的
最重要的学会面对多种运算不同的标记时应该如何处理他们之间的先后关系
以及对于求和时前后sum值之间的代数关系一定要写出来,便于理解
#include <bits/stdc++.h>
// 精品好题
using namespace std;
typedef long long ll;
const int MAXN = 1e5+7;
const int MOD = 10007;
ll add[MAXN<<2],se[MAXN<<2],mul[MAXN<<2];//add是加 set重置 mul乘 三种懒惰标记
ll sum1[MAXN<<2],sum2[MAXN<<2],sum3[MAXN<<2];//直接求和 平方和 立方和
// 多种操作时 要注意重置操作 优先级最高 重置之后 加等于0 乘等于1
// 在进行乘法操作时 如果当前有加法标记 那么加法标记也要相应的先乘以这个标记进行更新
// 而对于加法操作 因为涉及到平方和立方的操作 具体要推倒 新的节点与之前节点的值具有怎样的关系 关系找出来才能解决问题
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 rt,int l,int r)
{
add[rt] = se[rt] = 0;//都相当于一开始初始化操作
mul[rt] = 1;
if(l == r){
sum1[rt] = sum2[rt] = sum3[rt] = 0;
return ;
}
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void pushdown(int rt,int len)
{
if(se[rt]){
se[rt<<1] = se[rt<<1|1] = se[rt];
add[rt<<1] = add[rt<<1|1] = 0;// 当碰到重置的时候 先将加的变为0 乘的要变为1
mul[rt<<1] = mul[rt<<1|1] = 1;
ll tmp = ((se[rt] * se[rt]) % MOD) * se[rt] % MOD;
sum1[rt << 1] = ((len - (len >> 1)) % MOD) * (se[rt] % MOD) % MOD;
sum1[rt << 1 | 1] = ((len >> 1) % MOD) * (se[rt] % MOD) % MOD;
sum2[rt << 1] = ((len - (len >> 1)) % MOD) * ((se[rt] * se[rt]) % MOD) % MOD;
sum2[rt << 1 | 1] = ((len >> 1) % MOD) * ((se[rt] * se[rt]) % MOD) % MOD;
sum3[rt << 1] = ((len - (len >> 1)) % MOD) * tmp % MOD;
sum3[rt << 1 | 1] = ((len >> 1) % MOD) * tmp % MOD;
se[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 rt,int l,int r,int ul,int ur,int k,int c)
{
if(ul <= l && ur >= r) {
if(k == 3) {
se[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(k == 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(k == 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 mid = (l+r)>>1;
if(ul <= mid) update(rt<<1,l,mid,ul,ur,k,c);
if(ur > mid) update(rt<<1|1,mid+1,r,ul,ur,k,c);
pushup(rt);
}
ll query(int rt,int l,int r,int ql,int qr,int q)
{
if(l>=ql&&r<=qr){
if(q==1)
return sum1[rt];
else if(q==2)
return sum2[rt];
else
return sum3[rt];
}
pushdown(rt,r-l+1);
int mid = (l+r)>>1;
ll ans = 0;
if(ql <= mid) ans += query(rt<<1,l,mid,ql,qr,q);
if(qr > mid) ans += query(rt<<1|1,mid+1,r,ql,qr,q);
return ans%MOD;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&(n&&m)){
build(1,1,n);
int a,x,y,val;
while(m--){
scanf("%d%d%d%d",&a,&x,&y,&val);
if(a != 4){
update(1,1,n,x,y,a,val);
}
else{
printf("%lld\n",query(1,1,n,x,y,val));
}
}
}
return 0;
}