题目大意:n个数(初始为0)m个操作,操作类型有4中,操作1把区间的每个数+a,操作2把区间的每个数*a.,操作3把区间的每个数=a,操作4,查询区间每个数p次方的和(1<=p<=3)
对于=更新操作:如果之前有*和+的标记,那可以忽略到*+操作,直接=操作,这个最简单,sum1=val,sum2=val*val,sum3=val*val*val;
对于*+操作:如果之前有=标记,就不能忽略了,所以pushdown优先考略=操作。 *+操作可以一起(a*x+c).
注意:在*操作更新时,要一起更新+操作,因为(x+c)*a;
然后对于 (ax+c)^3=a^3*x^3+3*a^2*c*x^2+3*a*c^2*x+c^3,也就是root[t].sum3=a^3*root[t].sum3+3*a^2*c*root[t].sum2+3*a*c^2*root[t].sum1+c^3*(root[t].r-roo[t].l+1);
同理 root[t].sum2=root[t].sum2*a^2+root[t].sum1*c*2+c^2*(root[t].r-root[t].l+1); oot[t].sum1=root[t].sum1*a+c*(root[t].r-root[t].l+1);
注意:sum3,sum2,sum1在这个操作中的顺序不能变。
注意还要手写pow,以及pushdown操作,好多细节需要考虑
pushdown操作时,遇到mul就要更新pos<<1 和pos<<1|1的mul和lazy,遇到lazy就要更新pos<<1 和pos<<1|1的lazy
细节啊!!!!
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 100100
#define MOD 1000000007
const long long mod = 10007;
int n,m;
long long a[maxn*10];
struct node
{
int l,r;
long long Max,Min;
long long sum[4],lazy,mul,cover;
} tree[maxn*4];
long long pow(long long a,int b)
{
long long ans = 1;
for(int i = 0; i < b; i++)
ans = ans * a % mod;
return ans;
}
void pushup(int pos)
{
if(tree[pos].l == tree[pos].r)
return;
for(int i = 1; i < 4; i++)
tree[pos].sum[i] = (tree[pos<<1].sum[i] + tree[pos<<1|1].sum[i])%mod;
//tree[pos].Max = max(tree[pos<<1].Max,tree[pos<<1|1].Max);
//tree[pos].Min = min(tree[pos<<1].Min,tree[pos<<1|1].Min);
}
void pushdown(int pos)
{
if(tree[pos].l == tree[pos].r)
return;
if(tree[pos].cover != -1)
{
int l = tree[pos<<1].l,r = tree[pos<<1].r;
tree[pos<<1].lazy = 0;
tree[pos<<1].mul = 1;
tree[pos<<1].cover = tree[pos].cover;
for(int i = 1; i < 4; i++)
tree[pos<<1].sum[i] = (long long)(r-l+1)*(long long)pow(tree[pos].cover,i)%mod;
l = tree[pos<<1|1].l,r = tree[pos<<1|1].r;
tree[pos<<1|1].lazy = 0;
tree[pos<<1|1].mul = 1;
tree[pos<<1|1].cover = tree[pos].cover;
for(int i = 1; i < 4; i++)
tree[pos<<1|1].sum[i] = (long long)(r-l+1)*(long long)pow(tree[pos].cover,i)%mod;
tree[pos].cover = -1;
}
if(tree[pos].mul != 1)
{
tree[pos<<1].mul = (tree[pos<<1].mul * tree[pos].mul)%mod;
tree[pos<<1].lazy = (tree[pos<<1].lazy * tree[pos].mul) % mod;
for(int i = 1; i < 4; i++)
tree[pos<<1].sum[i] = (tree[pos<<1].sum[i] * (long long)pow(tree[pos].mul,i))%mod;
tree[pos<<1|1].mul = (tree[pos<<1|1].mul * tree[pos].mul)%mod;
tree[pos<<1|1].lazy = (tree[pos<<1|1].lazy * tree[pos].mul) % mod;
for(int i = 1; i < 4; i++)
tree[pos<<1|1].sum[i] = (tree[pos<<1|1].sum[i] * (long long)pow(tree[pos].mul,i))%mod;
tree[pos].mul = 1;
}
if(tree[pos].lazy)
{
int l = tree[pos<<1].l,r = tree[pos<<1].r;
long long add = tree[pos].lazy;
tree[pos<<1].lazy = (tree[pos<<1].lazy + tree[pos].lazy)%mod;
tree[pos<<1].sum[3] = (tree[pos<<1].sum[3]+3*tree[pos<<1].sum[1]*add*add+3*tree[pos<<1].sum[2]*add+(long long)(r-l+1)*add*add*add)%mod;
tree[pos<<1].sum[2] = (tree[pos<<1].sum[2]+2*tree[pos<<1].sum[1]*add+(long long)(r-l+1)*add*add)%mod;
tree[pos<<1].sum[1] = (tree[pos<<1].sum[1]+(long long)(r-l+1)*add)%mod;
l = tree[pos<<1|1].l,r = tree[pos<<1|1].r;
tree[pos<<1|1].lazy = (tree[pos<<1|1].lazy + tree[pos].lazy)%mod;
tree[pos<<1|1].sum[3] = (tree[pos<<1|1].sum[3]+3*tree[pos<<1|1].sum[1]*add*add+3*tree[pos<<1|1].sum[2]*add+(long long)(r-l+1)*add*add*add)%mod;
tree[pos<<1|1].sum[2] = (tree[pos<<1|1].sum[2]+2*tree[pos<<1|1].sum[1]*add+(long long)(r-l+1)*add*add)%mod;
tree[pos<<1|1].sum[1] = (tree[pos<<1|1].sum[1]+(long long)(r-l+1)*add)%mod;
tree[pos].lazy = 0;
}
}
void build(int l,int r,int pos)
{
tree[pos].l = l;
tree[pos].r = r;
for(int i = 0; i < 4; i++)
tree[pos].sum[i] = 0;
tree[pos].lazy = 0;
tree[pos].mul = 1;
tree[pos].cover = -1;
if(l == r)
{
//scanf("%lld",&tree[pos].sum);
//tree[pos].Max = tree[pos].sum;
// tree[pos].Min = tree[pos].sum;
return;
}
int mid = (l+r)/2;
build(l,mid,pos<<1);
build(mid+1,r,pos<<1|1);
//pushup(pos);
} //建树 //查询操作
void update(int l,int r,int pos,long long add,int choose)
{
add %= mod;
if(choose == 1)
{
if(tree[pos].l == l && tree[pos].r == r)
{
//tree[pos].sum += (r-l+1)*add;
//tree[pos].Max = add;
// tree[pos].Min += add;
tree[pos].sum[3] = (tree[pos].sum[3]+3*tree[pos].sum[1]*add*add+3*tree[pos].sum[2]*add+(long long)(r-l+1)*add*add*add)%mod;
tree[pos].sum[2] = (tree[pos].sum[2]+2*tree[pos].sum[1]*add+(long long)(r-l+1)*add*add)%mod;
tree[pos].sum[1] = (tree[pos].sum[1]+(long long)(r-l+1)*add)%mod;
tree[pos].lazy += add;
tree[pos].lazy %= mod;
return;
}
pushdown(pos);
int mid = (tree[pos].l + tree[pos].r) >> 1;
if(r <= mid)
update(l,r,pos<<1,add,choose);
else if(l > mid)
update(l,r,pos<<1|1,add,choose);
else if(l <= mid && r > mid)
{
update(l,mid,pos<<1,add,choose);
update(mid+1,r,pos<<1|1,add,choose);
}
pushup(pos);
}
else if(choose == 2)
{
if(tree[pos].l == l && tree[pos].r == r)
{
for(int i = 1; i < 4; i++)
tree[pos].sum[i] = (tree[pos].sum[i] * (long long)pow(add,i))%mod;
//tree[pos].Max = add;
//tree[pos].Min += add;
tree[pos].mul = tree[pos].mul * add % mod;
tree[pos].lazy = tree[pos].lazy * add % mod;
return;
}
pushdown(pos);
int mid = (tree[pos].l + tree[pos].r) >> 1;
if(r <= mid)
update(l,r,pos<<1,add,choose);
else if(l > mid)
update(l,r,pos<<1|1,add,choose);
else if(l <= mid && r > mid)
{
update(l,mid,pos<<1,add,choose);
update(mid+1,r,pos<<1|1,add,choose);
}
pushup(pos);
}
else
{
if(tree[pos].l == l && tree[pos].r == r)
{
for(int i = 1; i < 4; i++)
tree[pos].sum[i] = (long long)(r-l+1)*(long long)pow(add,i) % mod;
//tree[pos].Max = add;
//tree[pos].Min += add;
tree[pos].lazy = 0;
tree[pos].mul = 1;
tree[pos].cover = add;
return;
}
pushdown(pos);
int mid = (tree[pos].l + tree[pos].r) >> 1;
if(r <= mid)
update(l,r,pos<<1,add,choose);
else if(l > mid)
update(l,r,pos<<1|1,add,choose);
else if(l <= mid && r > mid)
{
update(l,mid,pos<<1,add,choose);
update(mid+1,r,pos<<1|1,add,choose);
}
pushup(pos);
}
} //自上而下更新节点
long long query(int l,int r,int pos,int choose)
{
if(tree[pos].l == l && tree[pos].r == r)
return tree[pos].sum[choose];
pushdown(pos);
int mid = (tree[pos].l+tree[pos].r)>>1;
if(r <= mid)
return query(l,r,pos<<1,choose);
else if(l > mid)
return query(l,r,pos<<1|1,choose);
else
return (query(l,mid,pos<<1,choose) + query(mid+1,r,pos<<1|1,choose))%mod;
}
int main()
{
int t,n,m,C = 1,num = 0;
//scanf("%d",&t);
//freopen("1.txt","r",stdin);
while(scanf("%d%d",&n,&m) && (n+m))
{
build(1,n,1);
//printf("Case %d:\n",C++);
while(m--)
{
int k,x,y,c;
scanf("%d%d%d%d",&k,&x,&y,&c);
if(k == 4)
//a[num++] = query(x,y,1,c)%mod;
printf("%lld\n",query(x,y,1,c)%mod);
else
update(x,y,1,(long long)c,k);
}
}
// freopen("2.txt","r",stdin);
// long long l;
// for(int i = 0; i < num; i++)
// {
// scanf("%lld",&l);
// if(l != a[i])
// printf("%d %d %lld %lld\n",i,b[i],l,a[i]);
// }
return 0;
}