题目:http://www.gdfzoj.com/oj/contest/285/problems/4
如题,已知一个数列,你需要进行下面三种操作:
1.将某区间每一个数乘上x
2.将某区间每一个数加上x
3.求出某区间每一个数的和
Input
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
Output
输出包含若干行整数,即为所有操作3的结果。
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
Sample Input
5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4
Sample Output
17 2
一开始以为add和mul要不断pushdown()向下更新,最终TLE
实际上add和mul有一定的关系
我们定义先乘后加
那么,先加后乘呢?直接add*mul不就可以了???!!!
so,我写了两份代码:
TLE的:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct node
{
long long l,r,add,mul,sum;
};
const int maxS=100000;
node M[maxS*4+5];
long long a[maxS+5];
int n,m,p;
void pushup(int x)
{
M[x].sum=(M[2*x].sum+M[2*x+1].sum)%p;
}
void pushdown(int x)
{
if (M[x].l==M[x].r)
return ;
if (M[x].add!=0)//只可能一个没更新
{
if (M[2*x].mul!=1)
pushdown(2*x);
if (M[2*x+1].mul!=1)
pushdown(2*x+1);
M[2*x].add=(M[2*x].add+M[x].add);
M[2*x+1].add=(M[2*x+1].add+M[x].add);
M[2*x].sum=(M[2*x].sum+M[x].add*(M[2*x].r-M[2*x].l+1))%p;
M[2*x+1].sum=(M[2*x+1].sum+M[x].add*(M[2*x+1].r-M[2*x+1].l+1))%p;
M[x].add=0;
}
else if (M[x].mul!=1)
{
if (M[2*x].add!=0)
pushdown(2*x);
if (M[2*x+1].add!=0)
pushdown(2*x+1);
M[2*x].mul=M[2*x].mul*M[x].mul%p;
M[2*x+1].mul=M[2*x+1].mul*M[x].mul%p;
M[2*x].sum=M[2*x].sum*M[x].mul%p;
M[2*x+1].sum=M[2*x+1].sum*M[x].mul%p;
M[x].mul=1;
}
}
void build(int x,int l,int r)
{
int mid=(l+r)/2;
M[x].l=l; M[x].r=r; M[x].sum=0;
M[x].add=0; M[x].mul=1;
if (l==r)
{
M[x].sum=a[l];
return ;
}
build(2*x,l,mid);
build(2*x+1,mid+1,r);
pushup(x);
}
void add(int x,int l,int r,int k)
{
int mid=(M[x].l+M[x].r)/2;
if (l==M[x].l&& r==M[x].r)
{
if (M[x].mul!=1 && l!=r)
pushdown(x);
M[x].add+=k;
M[x].sum=(M[x].sum+k*(M[x].r-M[x].l+1))%p;
return ;
}
pushdown(x);
if (r<=mid)
add(2*x,l,r,k);
else if (l>mid)
add(2*x+1,l,r,k);
else
{
add(2*x,l,mid,k);
add(2*x+1,mid+1,r,k);
}
pushup(x);
}
void mul(int x,int l,int r,int k)
{
int mid=(M[x].l+M[x].r)/2;
if (M[x].l==l && M[x].r==r)
{
if (M[x].add!=0 && l!=r)
pushdown(x);
M[x].mul=M[x].mul*k%p;
M[x].sum=M[x].sum*k%p;
return ;
}
pushdown(x);
if (r<=mid)
mul(2*x,l,r,k);
else if (l>mid)
mul(2*x+1,l,r,k);
else
{
mul(2*x,l,mid,k);
mul(2*x+1,mid+1,r,k);
}
pushup(x);
}
long long query(int x,int l,int r)
{
int mid=(M[x].l+M[x].r)/2;
if (M[x].l==l && M[x].r==r)
return M[x].sum;
pushdown(x);
if (r<=mid)
return query(2*x,l,r);
else if (l>mid)
return query(2*x+1,l,r);
else
return (query(2*x,l,mid)+query(2*x+1,mid+1,r))%p;
}
int main()
{
int i,x,y,t1,k;
freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);
scanf("%d%d%d",&n,&m,&p);
for (i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for (i=1;i<=m;i++)
{
scanf("%d",&t1);
if (t1==1)
{
scanf("%d%d%d",&x,&y,&k);
mul(1,x,y,k);
}
else if (t1==2)
{
scanf("%d%d%d",&x,&y,&k);
add(1,x,y,k);
}
else
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(1,x,y)%p);
}
}
return 0;
}
ac的:在上一份代码的基础上修改的,但漏改了一个地方差点gg
//定义先乘后加
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct node
{
long long l,r,add,mul,sum;
};
const int maxS=100000;
node M[maxS*4+5];
long long a[maxS+5];
long long n,m,p;
void pushup(int x)
{
M[x].sum=(M[2*x].sum+M[2*x+1].sum)%p;
}
void pushdown(int x)//先加后乘
{
// if (M[x].l==M[x].r)
// return ;
if (M[x].mul!=1)//先乘后加
{
M[2*x].mul=M[2*x].mul*M[x].mul%p;
M[2*x].add=M[2*x].add*M[x].mul%p;
M[2*x+1].mul=M[2*x+1].mul*M[x].mul%p;
M[2*x+1].add=M[2*x+1].add*M[x].mul%p;
M[2*x].sum=M[2*x].sum*M[x].mul%p;
M[2*x+1].sum=M[2*x+1].sum*M[x].mul%p;
M[x].mul=1;
}
if (M[x].add!=0)
{
M[2*x].add=(M[2*x].add+M[x].add)%p;
M[2*x+1].add=(M[2*x+1].add+M[x].add)%p;
M[2*x].sum=(M[2*x].sum+M[x].add*(M[2*x].r-M[2*x].l+1))%p;
M[2*x+1].sum=(M[2*x+1].sum+M[x].add*(M[2*x+1].r-M[2*x+1].l+1))%p;
M[x].add=0;
}
}
void build(int x,int l,int r)
{
int mid=(l+r)/2;
M[x].l=l; M[x].r=r; M[x].sum=0;
M[x].add=0; M[x].mul=1;
if (l==r)
{
M[x].sum=a[l];
return ;
}
build(2*x,l,mid);
build(2*x+1,mid+1,r);
pushup(x);
}
void add(int x,int l,int r,int k)
{
int mid=(M[x].l+M[x].r)/2;
if (l==M[x].l&& r==M[x].r)
{
M[x].add=(M[x].add+k)%p;
M[x].sum=(M[x].sum+k*(M[x].r-M[x].l+1))%p;
return ;
}
pushdown(x);
if (r<=mid)
add(2*x,l,r,k);
else if (l>mid)
add(2*x+1,l,r,k);
else
{
add(2*x,l,mid,k);
add(2*x+1,mid+1,r,k);
}
pushup(x);
}
void mul(int x,int l,int r,int k)
{
int mid=(M[x].l+M[x].r)/2;
if (M[x].l==l && M[x].r==r)
{
M[x].add=M[x].add*k%p;
M[x].mul=M[x].mul*k%p;
M[x].sum=M[x].sum*k%p;
return ;
}
pushdown(x);
if (r<=mid)
mul(2*x,l,r,k);
else if (l>mid)
mul(2*x+1,l,r,k);
else
{
mul(2*x,l,mid,k);
mul(2*x+1,mid+1,r,k);
}
pushup(x);
}
long long query(int x,int l,int r)
{
int mid=(M[x].l+M[x].r)/2;
if (M[x].l==l && M[x].r==r)
return M[x].sum;
pushdown(x);
if (r<=mid)
return query(2*x,l,r)%p;
else if (l>mid)
return query(2*x+1,l,r)%p;
else
return (query(2*x,l,mid)+query(2*x+1,mid+1,r))%p;
}
int main()
{
int i,x,y,t1,k;
freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);
scanf("%lld%lld%lld",&n,&m,&p);
for (i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for (i=1;i<=m;i++)
{
scanf("%d",&t1);
if (t1==1)
{
scanf("%d%d%d",&x,&y,&k);
mul(1,x,y,k);
}
else if (t1==2)
{
scanf("%d%d%d",&x,&y,&k);
add(1,x,y,k);
}
else
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(1,x,y));
}
}
return 0;
}