小阳的贝壳
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
小阳手中一共有 n 个贝壳,每个贝壳都有颜色,且初始第 i 个贝壳的颜色为 coli。现在小阳有 3 种操作:
1 l r x:给 [l,r] 区间里所有贝壳的颜色值加上 x 。
2 l r:询问 [l,r] 区间里所有相邻贝壳 颜色值的差(取绝对值) 的最大值(若 l=r输出 0)。
3 l r :询问 [l,r]区间里所有贝壳颜色值的最大公约数。
输入描述:
第一行输入两个正整数 n,m,分别表示贝壳个数和操作个数。
第二行输入 n 个数 coli,表示每个贝壳的初始颜色。
第三到第 m+2 行,每行第一个数为 opt,表示操作编号。接下来的输入的变量与操作编号对应。
输出描述:
共 m 行,对于每个询问(操作 2 和操作 3)输出对应的结果。
示例1
输入
复制
5 6
2 2 3 3 3
1 2 3 3
2 2 4
3 3 5
1 1 4 2
3 2 3
2 3 5
输出
复制
3
3
1
3
备注:
1≤n,m≤105,1≤coli,x≤103,1≤opt≤3,1≤l≤r≤n
链接:https://ac.nowcoder.com/acm/contest/949/H
差分:区间[l,r]统一加上x,只需要 f[l]+x , f[r]-x
#include <iostream>
using namespace std;
struct node
{
int v;//差分数
int maxv;
int gcdv;
}tree[100005*4];
int n,q;
int a[100005];
int read()
{
char ch=getchar();
int x=0,f=0;
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
void build(int l,int r,int i)
{
if(l==r)
{
tree[i].maxv=tree[i].gcdv=abs(a[l]);
tree[i].v=a[l];
return;
}
int mid=(l+r)/2;
build(l,mid,i+i);
build(mid+1,r,i+i+1);
tree[i].maxv=max(tree[i+i].maxv,tree[i+i+1].maxv);
tree[i].gcdv=gcd(tree[i+i].gcdv,tree[i+i+1].gcdv);
tree[i].v=tree[i+i].v+tree[i+i+1].v;
}
void updata(int l,int r,int i,int id,int x)
{
if(l==r)
{
a[l]+=x;
tree[i].maxv=tree[i].gcdv=abs(a[l]);
tree[i].v=a[l];
return;
}
int mid=(l+r)/2;
if(mid>=id)
updata(l,mid,i+i,id,x);
else
updata(mid+1,r,i+i+1,id,x);
tree[i].maxv=max(tree[i+i].maxv,tree[i+i+1].maxv);
tree[i].gcdv=gcd(tree[i+i].gcdv,tree[i+i+1].gcdv);
tree[i].v=tree[i+i].v+tree[i+i+1].v;
}
int query_max(int l,int r,int i,int ll,int rr)
{
if(ll<=l&&r<=rr)
return abs(tree[i].maxv);
int mid=(l+r)/2;
int res=0;
if(ll<=mid)
res=max(res,query_max(l,mid,i+i,ll,rr));
if(mid<rr)
res=max(res,query_max(mid+1,r,i+i+1,ll,rr));
return res;
}
int query_gcd(int l,int r,int i,int ll,int rr)
{
if(ll<=l&&r<=rr)
return tree[i].gcdv;
int mid=(l+r)/2;
int res=0;
if(ll<=mid)
res=gcd(res,query_gcd(l,mid,i+i,ll,rr));
if(mid<rr)
res=gcd(res,query_gcd(mid+1,r,i+i+1,ll,rr));
return res;
}
int query_sum(int l,int r,int i,int ll,int rr)
{
if(ll<=l&&r<=rr)
return tree[i].v;
int mid=(l+r)/2;
int res=0;
if(ll<=mid)
res+=query_sum(l,mid,i+i,ll,rr);
if(mid<rr)
res+=query_sum(mid+1,r,i+i+1,ll,rr);
return res;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
a[i]=read();
}
for(int i=n;i>0;i--)
{
a[i]=a[i]-a[i-1];
}
build(1,n,1);
int op,l,r,x;
while(q--)
{
op=read();
if(op==1)
{
l=read();
r=read();
x=read();
updata(1,n,1,l,x);
if(r<n)
updata(1,n,1,r+1,-x);
}
else if(op==2)
{
l=read();
r=read();
printf("%d\n",query_max(1,n,1,l+1,r));
}
else
{
l=read();
r=read();
int res_a=query_sum(1,n,1,1,l);
printf("%d\n",gcd(res_a,query_gcd(1,n,1,l+1,r)));
}
}
return 0;
}