luogu1890 gcd区间

本文介绍了一种使用线段树解决区间最大公因数查询问题的方法。通过构造线段树来维护区间上的最大公因数值,实现了快速响应多次区间查询的需求。

题目大意:给定一行n个正整数a[1]..a[n]。m次询问,每次询问给定一个区间[L,R],输出a[L]..a[R]的最大公因数。

因为gcd满足交换律和结合律,所以用线段树维护区间上的gcd值即可。

#include <cstdio>
#include <cstring>
using namespace std;

const int MAX_RANGE = 1010;

int GetGcd(int a, int b)
{
	return b ? GetGcd(b, a % b) : a;
}

struct GcdRangeTree
{
private:
	int Gcd[MAX_RANGE * 4];
	int N;

	void PullUp(int cur)
	{
		Gcd[cur] = GetGcd(Gcd[cur * 2], Gcd[cur * 2 + 1]);
	}

	void Init(int cur, int sl, int sr, int *a)
	{
		if (sl == sr)
		{
			Gcd[cur] = a[sr];
			return;
		}
		int mid = (sl + sr) / 2;
		Init(cur * 2, sl, mid, a);
		Init(cur * 2 + 1, mid + 1, sr, a);
		PullUp(cur);
	}

	int Query(int cur, int sl, int sr, int al, int ar)
	{
		//printf("cur(%d,%d) find(%d,%d)\n", sl, sr, al, ar);
		if (al <= sl && sr <= ar)
			return Gcd[cur];
		int ans=0, mid = (sl + sr) / 2;
		if (al <= mid)
			ans = Query(cur * 2, sl, mid, al, ar);
		if (ar > mid)
		{
			if (ans)
				ans = GetGcd(ans, Query(cur * 2 + 1, mid + 1, sr, al, ar));
			else
				ans = Query(cur * 2 + 1, mid + 1, sr, al, ar);
		}
		return ans;
	}

public:
	GcdRangeTree(int n, int *a)
	{
		N = n;
		memset(Gcd, 0, sizeof(Gcd));
		Init(1, 1, N, a);
	}

	int Query(int l, int r)
	{
		return Query(1, 1, N, l, r);
	}
};

int main()
{
	int range, opCnt;
	static int a[MAX_RANGE];
	scanf("%d%d", &range, &opCnt);
	for (int i = 1; i <= range; i++)
		scanf("%d", a + i);
	static GcdRangeTree g(range, a);
	while (opCnt--)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		printf("%d\n", g.Query(l, r));
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/headboy2002/p/8893526.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值