牛客网 小阳的贝壳(线段树+差分数组+gcd)

小阳的贝壳

时间限制: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

备注:

扫描二维码关注公众号,回复: 8789406 查看本文章
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;
}
发布了39 篇原创文章 · 获赞 27 · 访问量 4118

猜你喜欢

转载自blog.csdn.net/qq_43381887/article/details/102572979
今日推荐