博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

CF 474F 区间查询gcd==x

题目大意

给定一个序列,支持查询区间中等于gcd的数字有多少个,输出\(len - num\)

\(n \leq 10^5\)

思路

一个区间等于gcd的数字个数取决于两个子区间的数字个数。判断即可

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

int a[N];
int n,m;
struct  node
{
	int l,r;
	int sum;
	int gcd;
}t[N << 2];


int gcd(int a,int b) {
	return b == 0 ? a : gcd(b,a % b);
}

void update(int rt) {
	int ch = rt << 1;
	t[rt].gcd = gcd(t[ch].gcd,t[ch + 1].gcd);
	if(t[ch].gcd == t[ch + 1].gcd) t[rt].sum = t[ch].sum + t[ch + 1].sum;
	else if(t[rt].gcd == t[ch].gcd) t[rt].sum = t[ch].sum;
	else if(t[rt].gcd == t[ch + 1].gcd) t[rt].sum = t[ch + 1].sum;
	else t[rt].sum = 0;
}

void build(int l,int r,int rt) {
	t[rt].l = l;
	t[rt].r = r;
	if(l == r) {
		t[rt].gcd = a[l];
		t[rt].sum = 1;
		return;
	}
	int ch = rt << 1;
	int mid = (l + r) >> 1; 
	build(l,mid,ch);
	build(mid + 1,r,ch + 1);
	update(rt);
}

node query(int l,int r,int rt) {
	if(l == t[rt].l and r == t[rt].r) {
		return t[rt];
	}
	int mid = (t[rt].l + t[rt].r) >> 1;
	int ch = rt << 1;
	if(r <= mid) {
		return query(l,r,ch);
	}
	else if(l > mid) {
		return query(l,r,ch + 1);
	}else {
		node tmp1 = query(l,mid,ch);
		node tmp2 = query(mid + 1,r,ch + 1);
		node res;
		res.l = l;
		res.r = r;
		res.gcd = gcd(tmp1.gcd,tmp2.gcd);
		if(tmp1.gcd == tmp2.gcd) res.sum = tmp1.sum + tmp2.sum;
		else if(res.gcd == tmp1.gcd) res.sum = tmp1.sum;
		else if(res.gcd == tmp2.gcd) res.sum = tmp2.sum;
		else res.sum = 0;
		return res;
	}
}

int main () {
	scanf("%d",&n);
	for(int i = 1;i <= n; i ++) {
		scanf("%d",&a[i]);
	}
	build(1,n,1);
	cin >> m;
	while(m --) {
		int l,r;
		scanf("%d %d",&l,&r);
		printf("%d\n",r - l + 1 - query(l,r,1).sum);
	}
	return 0;
}
posted @ 2022-02-13 19:41  Allorkiya  阅读(15)  评论(0编辑  收藏  举报