Bash and a Tough Math Puzzle 线段树维护区间gcd

还是一道很不错的题目,很容易想到用一棵线段树来维护区间gcd

注意用倍数来剪枝就好了,很是一到很好的题目的

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;
const int N = 5e5+10;
int n,q;
struct Segment{
	int l,r;
	int d;
}tr[N<<2];

int w[N];
int res;
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}

void pushup(int u){
	tr[u].d = gcd(tr[u<<1].d,tr[u<<1|1].d);
}

void build(int u,int l,int r){
	tr[u] = {l,r};
	if(l==r){tr[u].d = w[l];return;}
	int mid = l+r>>1;
	build(u<<1,l,mid),build(u<<1|1,mid+1,r);
	pushup(u);
}

void modify(int u,int x,int c){
	if(tr[u].l==tr[u].r&&tr[u].l==x){
		tr[u].d = c;return; 
	}
	
	int mid = (tr[u].l+tr[u].r)>>1;
	if(x<=mid)modify(u<<1,x,c);
	else modify(u<<1|1,x,c);
	pushup(u);
}

void query(int u,int l,int r,int x){
	
	if(res>1)return;
	if(l<=tr[u].l&&tr[u].r<=r){
		if(tr[u].d%x==0)return;
	}
	if(tr[u].l==tr[u].r){
		res+=(tr[u].d%x!=0);
		return;
	}
	
	int mid = tr[u].l+tr[u].r>>1;
	if(l<=mid)query(u<<1,l,r,x);
	if(r>mid)query(u<<1|1,l,r,x);
	
	
}


int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>w[i];
	cin>>q;
	build(1,1,n);
	while(q--){
		int op;cin>>op;
		if(op==1){
			int l,r,x;cin>>l>>r>>x;
			res = 0;
			query(1,l,r,x);
			if(res>1)cout<<"NO"<<"\n";
			else cout<<"YES\n";
			
		}else{
			int x,c;cin>>x>>c;
			modify(1,x,c);
		}
	}
}
相关推荐
西幻凌云14 小时前
认识STL序列式容器——List
开发语言·c++·stl·list·序列式容器
~无忧花开~14 小时前
JavaScript实现PDF本地预览技巧
开发语言·前端·javascript
靠沿14 小时前
Java数据结构初阶——LinkedList
java·开发语言·数据结构
4***997415 小时前
Kotlin序列处理
android·开发语言·kotlin
froginwe1115 小时前
Scala 提取器(Extractor)
开发语言
t***D26415 小时前
Kotlin在服务端开发中的生态建设
android·开发语言·kotlin
mini_05515 小时前
mac电脑免费使用Typora教程
macos
Elias不吃糖15 小时前
LeetCode每日一练(209, 167)
数据结构·c++·算法·leetcode
Want59515 小时前
C/C++跳动的爱心②
c语言·开发语言·c++