http://acm.hdu.edu.cn/showproblem.php?pid=4578
又做了一道好题。。
有三种操作:
1 a b c [a,b]加上c
2 a b c [a,b]乘上c
3 a b c [a,b]变为c
4 a b c 求[a,b]的c次方和(1<=c<=3)
这题首先需要解决的第一个问题是加上或乘上一个数对这个区间的c次方和分别产生什么改变,很简单,一化简就能得到。
第二个问题是当一段区间上既有乘又有加的lazy时应该怎么向下推送,因为一段区间上只能有一个lazy,我起初做的是先将有lazy的标记向下传,直到不冲突为止,然后更新这个区间的lazy,后来无数次的wa。代码太长了,简直无法debug。
同学说要找到这两个lazy的关系,即可以把每个数看做mult * x + add。加上一个数y时,add+= y,乘上一个数y时,mult *= y,add *= y。这样就解决了先加后乘和先乘后加的问题了,感觉好机智,mark。
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
//#define LL long long
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
const int mod = 10007;
struct node
{
int l,r;
int mult,add;
int s[4];
} tree[maxn*4];
void build(int v, int l, int r)
{
tree[v].l = l;
tree[v].r = r;
tree[v].mult = 1;
tree[v].add = 0;
tree[v].s[1] = tree[v].s[2] = tree[v].s[3] = 0;
if(l == r)
return;
int mid = (l+r)>>1;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
}
void cal(int v,int mult, int add)
{
int len = tree[v].r - tree[v].l + 1;
tree[v].s[1] = tree[v].s[1] * mult%mod;
tree[v].s[2] = tree[v].s[2] * mult%mod*mult%mod;
tree[v].s[3] = tree[v].s[3] * mult%mod*mult%mod*mult%mod;
tree[v].mult = (tree[v].mult * mult)%mod;
tree[v].add = (tree[v].add * mult)%mod;
tree[v].s[3] = (tree[v].s[3] + 3*add%mod*add%mod*tree[v].s[1]%mod)%mod;
tree[v].s[3] = (tree[v].s[3] + 3*add%mod*tree[v].s[2]%mod)%mod;
tree[v].s[3] = (tree[v].s[3] + len*add%mod*add%mod*add%mod)%mod;
tree[v].s[2] = (tree[v].s[2] + 2*add%mod*tree[v].s[1]%mod)%mod;
tree[v].s[2] = (tree[v].s[2] + len*add%mod*add%mod)%mod;
tree[v].s[1] = (tree[v].s[1] + len*add%mod)%mod;
tree[v].add = (tree[v].add + add)%mod;
}
void push_down(int v)
{
if(tree[v].l == tree[v].r)
return;
cal(v*2,tree[v].mult,tree[v].add);
cal(v*2+1,tree[v].mult,tree[v].add);
tree[v].mult = 1;
tree[v].add = 0;
}
void push_up(int v)
{
int ls = v*2,rs = v*2+1;
tree[v].s[1] = (tree[ls].s[1] + tree[rs].s[1])%mod;
tree[v].s[2] = (tree[ls].s[2] + tree[rs].s[2])%mod;
tree[v].s[3] = (tree[ls].s[3] + tree[rs].s[3])%mod;
}
void update(int v, int l, int r, int mult, int add)
{
if(tree[v].l == l && tree[v].r == r)
{
cal(v,mult,add);
return;
}
push_down(v);
int mid = (tree[v].l + tree[v].r) >> 1;
if(r <= mid)
update(v*2,l,r,mult,add);
else if(l > mid)
update(v*2+1,l,r,mult,add);
else
{
update(v*2,l,mid,mult,add);
update(v*2+1,mid+1,r,mult,add);
}
push_up(v);
}
int query(int v, int l, int r,int p)
{
if(tree[v].l == l && tree[v].r == r)
{
return tree[v].s[p];
}
push_down(v);
int mid = (tree[v].l + tree[v].r) >> 1;
if(r <= mid)
return query(v*2,l,r,p);
else if(l > mid)
return query(v*2+1,l,r,p);
else
return (query(v*2,l,mid,p) + query(v*2+1,mid+1,r,p))%mod;
}
int main()
{
int n,m;
int op,x,y,c;
while(~scanf("%d %d",&n,&m))
{
if(n == 0 && m == 0) break;
build(1,1,n);
while(m--)
{
scanf("%d %d %d %d",&op,&x,&y,&c);
if(op == 1)
update(1,x,y,1,c);
else if(op == 2)
update(1,x,y,c,0);
else if(op == 3)
update(1,x,y,0,c);
else
printf("%d\n",query(1,x,y,c)%mod);
}
}
return 0;
}