列表

详情


NC26255. 小阳的贝壳

描述

小阳手中一共有 n 个贝壳,每个贝壳都有颜色,且初始第 i 个贝壳的颜色为 col_i 。现在小阳有 3 种操作:

1 l r x:给 区间里所有贝壳的颜色值加上

2 l r:询问 区间里所有相邻贝壳 颜色值的差(取绝对值) 的最大值(若 输出 0)。

3 l r :询问 区间里所有贝壳颜色值的最大公约数。

输入描述

第一行输入两个正整数 ,分别表示贝壳个数和操作个数。
第二行输入 个数 ,表示每个贝壳的初始颜色。
第三到第 行,每行第一个数为 ,表示操作编号。接下来的输入的变量与操作编号对应。

输出描述

共 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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 103ms, 内存消耗: 5920K, 提交时间: 2020-07-09 10:40:06

#include<bits/stdc++.h>
using namespace std;
const int mx=4e5+5;
int s[mx],t[mx],d[mx],a[100005];
inline void work(int p){
	s[p]=s[p*2]+s[p*2+1];
	t[p]=max(t[p*2],t[p*2+1]);
	d[p]=__gcd(d[p*2],d[p*2+1]);
}
void build(int p,int l,int r){
	if(l==r){
		s[p]=a[l],t[p]=d[p]=abs(a[l]);
		return;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid),build(p*2+1,mid+1,r);
	work(p);
}
void change(int p,int l,int r,int x){
	if(l==r){
		s[p]=a[l],t[p]=d[p]=abs(a[l]);
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid)change(p*2,l,mid,x);
	else change(p*2+1,mid+1,r,x);
	work(p);
}
int query(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return t[p];
	int mid=(l+r)>>1,a1=0,a2=0;
	if(x<=mid)a1=query(p*2,l,mid,x,y);
	if(mid<y)a2=query(p*2+1,mid+1,r,x,y);
	return max(a1,a2); 
}
int get(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return s[p];
	int mid=(l+r)>>1,re=0;
	if(x<=mid)re+=get(p*2,l,mid,x,y);
	if(mid<y)re+=get(p*2+1,mid+1,r,x,y);
	return re;
}
int find(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return d[p];
	int mid=l+r>>1,a1=0,a2=0;
	if(x<=mid)a1=find(p*2,l,mid,x,y);
	if(mid<y)a2=find(p*2+1,mid+1,r,x,y);
	return __gcd(a1,a2);
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%d",a+i);
	for(int i=n;i;--i)a[i]-=a[i-1];
	build(1,1,n);
	int op,l,r,x;
	while(m--){
		scanf("%d%d%d",&op,&l,&r);
		if(op==1){
			scanf("%d",&x);
			a[l]+=x,change(1,1,n,l);
			if(r+1<=n)a[r+1]-=x,change(1,1,n,r+1); 
		}
		else if(op==2){
			if(l==r)puts("0");
			else printf("%d\n",query(1,1,n,l+1,r)); 
		}
		else printf("%d\n",__gcd(get(1,1,n,1,l),find(1,1,n,l+1,r)));
	}
}

C++(clang++ 11.0.1) 解法, 执行用时: 149ms, 内存消耗: 4120K, 提交时间: 2022-09-14 01:12:19

#include<bits/stdc++.h> 
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
const int N=1e5+5; int n,v[N];
struct Seg{
	int s,m,t;
	inline Seg operator +(const Seg &z) const{return {s+z.s,max(m,z.m),__gcd(t,z.t)};}
}a[N<<2];
void pushup(int x) {a[x]=a[ls]+a[rs];}
void build(int x,int l,int r) {
	if (l==r) return a[x]={v[l],abs(v[l]),v[l]},void(); int mid=l+r>>1;
	build(ls,l,mid),build(rs,mid+1,r),pushup(x);
}
void update(int x,int l,int r,int p) {
	if (l==r) return a[x]={v[l],abs(v[l]),v[l]},void(); int mid=l+r>>1;
	if (p<=mid) update(ls,l,mid,p); else update(rs,mid+1,r,p); pushup(x);
}
Seg query(int x,int l,int r,int p,int q) {
	if (p>q) return {0,0,0};
	if (p<=l&&r<=q) return a[x]; int mid=l+r>>1;
	if (q<=mid) return query(ls,l,mid,p,q);
	else if (mid<p) return query(rs,mid+1,r,p,q);
	else return query(ls,l,mid,p,q)+query(rs,mid+1,r,p,q);
}
int main() {
	int T,i,x,y=0,z,q;
	scanf("%d%d",&n,&T);
	for (i=1;i<=n;i++) scanf("%d",v+i);
	for (i=n;i>1;i--) v[i]-=v[i-1];
	build(1,1,n);
	for (;T--;) {
		scanf("%d%d%d",&q,&x,&y);
		if (q==1) {
			scanf("%d",&z);
			v[x]+=z,update(1,1,n,x);
			if (y<n) v[y+1]-=z,update(1,1,n,y+1);
		}
		if (q==2) printf("%d\n",query(1,1,n,x+1,y).m);
		if (q==3) printf("%d\n",abs(__gcd(query(1,1,n,1,x).s,query(1,1,n,x+1,y).t)));
	}
}

上一题