http://acm.hdu.edu.cn/showproblem.php?pid=4578
Problem Description
Yuanfang is puzzled with the question below:
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<—ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<—ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<—c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
题意:
1.将a~b都加上c
2.将a~b都乘上c
3.将a~b都变成c
4.查询a~b的每个数的p次方的和。(p=1,2,3)
思路:依次做了加+乘以及加+覆盖,才来做这道题,懒标记优先次序: setv>mulv>addv,即后者是在前者的基础上的标记。直接在区间内维护1、2、3次方的sum即可。
更新和查询都是pushdown到目标区间。
#include<bits/stdc++.h>
using namespace std;
#define maxn (100000+100)
#define ll long long
#define M(x) (x%=10007)
int n,m;
ll op,ql,qr,val,_sum;
struct SegmentTree{
ll sumv[maxn*4][4],addv[maxn*4],mulv[maxn*4],setv[maxn*4];
void build(int o,int l,int r)
{
if(l==r)
{
for(int i=1;i<=3;i++)sumv[o][i]=0;
setv[o]=0;addv[o]=0;mulv[o]=1;
}
else
{
int mid=(l+r)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
setv[o]=-1;addv[o]=0;mulv[o]=1;
for(int i=1;i<=3;i++)sumv[o][i]=0;
}
}
void pushdown(int o)
{
if(setv[o]>=0)
{
setv[o*2]=setv[o*2+1]=setv[o];
addv[o*2]=addv[o*2+1]=0;
mulv[o*2]=mulv[o*2+1]=1;
setv[o]=-1;
}
if(mulv[o]>1)
{
addv[o*2]*=mulv[o];M(addv[o*2]);addv[o*2+1]*=mulv[o];M(addv[o*2+1]);
mulv[o*2]*=mulv[o];mulv[o*2+1]*=mulv[o];M(mulv[o*2]);M(mulv[o*2+1]);
mulv[o]=1;
}
if(addv[o]>0)
{
addv[o*2]+=addv[o];M(addv[o*2]);
addv[o*2+1]+=addv[o];M(addv[o*2+1]);
addv[o]=0;
}
}
void maintain(int o,int l,int r)
{
if(l<r) for(int i=1;i<=3;i++)sumv[o][i]=sumv[o*2][i]+sumv[o*2+1][i],M(sumv[o][i]);
else for(int i=1;i<=3;i++)sumv[o][i]=0;
if(setv[o]>=0)
{
sumv[o][1]=(r-l+1)*setv[o];
sumv[o][2]=(r-l+1)*setv[o]*setv[o];
sumv[o][3]=(r-l+1)*setv[o]*setv[o]*setv[o];
for(int i=1;i<=3;i++)M(sumv[o][i]);
}
if(mulv[o]>1)
{
sumv[o][1]*=mulv[o];
sumv[o][2]*=mulv[o]*mulv[o];
sumv[o][3]*=mulv[o]*mulv[o]*mulv[o];
for(int i=1;i<=3;i++)M(sumv[o][i]);
}
if(addv[o]>0)
{
int s1=sumv[o][1],s2=sumv[o][2];
sumv[o][1]+=addv[o]*(r-l+1);
sumv[o][2]+=2*s1*addv[o]+addv[o]*addv[o]*(r-l+1);
sumv[o][3]+=3*addv[o]*addv[o]*s1+3*s2*addv[o]+addv[o]*addv[o]*addv[o]*(r-l+1);
for(int i=1;i<=3;i++)M(sumv[o][i]);
}
}
void update(int o,int l,int r)
{
if(ql<=l&&qr>=r)
{
if(op==1)addv[o]+=val;
else if(op==2)mulv[o]*=val,addv[o]*=val;
else setv[o]=val,addv[o]=0,mulv[o]=1;
M(addv[o]);M(mulv[o]);M(setv[o]);
}
else
{
int mid=(l+r)/2;
pushdown(o);
maintain(o*2,l,mid);maintain(o*2+1,mid+1,r);
if(ql<=mid)update(o*2,l,mid);
if(qr>mid)update(o*2+1,mid+1,r);
}
maintain(o,l,r);
}
void query(int o,int l,int r)
{
if(ql<=l&&qr>=r)_sum+=sumv[o][val],M(_sum);
else
{
int mid=(l+r)/2;
pushdown(o);
maintain(o*2,l,mid);maintain(o*2+1,mid+1,r);
maintain(o,l,r);
if(ql<=mid)query(o*2,l,mid);
if(qr>mid)query(o*2+1,mid+1,r);
}
}
}tree;
int main()
{
//freopen("input.in","r",stdin);
while(cin>>n>>m&&n)
{
tree.build(1,1,n);
while(m--)
{
scanf("%lld%lld%lld%lld",&op,&ql,&qr,&val);M(val);
if(op!=4)tree.update(1,1,n);
else
{
_sum=0;
tree.query(1,1,n);
printf("%lld\n",_sum);
}
}
}
return 0;
}