2019 ICPC Asia Yinchuan Regional G. Pot!!

2019 ICPC Asia Yinchuan Regional

【题目大意】

【解题思路】
在线段树上打4个标记分别表示将节点权值分解为2,4,5,7的个数,或者开4颗线段树也可

【AC代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
inline ll max(ll a, ll b) { return a > b ? a : b; }
struct Tree
{
	int l, r;
	ll flag2;
	ll flag3;
	ll flag5;
	ll flag7;
	ll lazy[5];
}tree[maxn];
inline void pushdown(int root)
{
	tree[root].flag2 += tree[root].lazy[1];
	tree[root].flag3 += tree[root].lazy[2];
	tree[root].flag5 += tree[root].lazy[3];
	tree[root].flag7 += tree[root].lazy[4];
	for (int i = 1; i <= 4; ++i)
	{
		tree[root << 1].lazy[i] += tree[root].lazy[i];
		tree[root << 1 | 1].lazy[i] += tree[root].lazy[i];
		tree[root].lazy[i] = 0;
	}
}
inline void build(int root, int l, int r)
{
	tree[root].l = l;
	tree[root].r = r;
	tree[root].flag2 = tree[root].flag3 = tree[root].flag5 = tree[root].flag7 = 0;
	for (int i = 1; i <= 4; ++i)
	{
		tree[root].lazy[i] = 0;
	}
	if (l == r) return;
	register int mid = (l + r) >> 1;
	build(root << 1, l, mid);
	build(root << 1 | 1, mid + 1, r);
}
inline void update(int root, int l, int r, ll val)
{
	if (l <= tree[root].l && tree[root].r <= r)
	{
		while (val % 2 == 0)
		{
			++tree[root].lazy[1];
			val /= 2;
		}
		while (val % 3 == 0)
		{
			++tree[root].lazy[2];
			val /= 3;
		}
		while (val % 5 == 0)
		{
			++tree[root].lazy[3];
			val /= 5;
		}
		while (val % 7 == 0)
		{
			++tree[root].lazy[4];
			val /= 7;
		}
		pushdown(root);
		return;
	}
	pushdown(root);
	register int mid = (tree[root].l + tree[root].r) >> 1;
	if (mid >= r) update(root << 1, l, r, val);
	else if (mid < l) update(root << 1 | 1, l, r, val);
	else
	{
		update(root << 1, l, mid, val);
		update(root << 1 | 1, mid + 1, r, val);
	}
	tree[root].flag2 = max(tree[root].flag2, max(tree[root << 1].flag2, tree[root << 1 | 1].flag2));
	tree[root].flag3 = max(tree[root].flag3, max(tree[root << 1].flag3, tree[root << 1 | 1].flag3));
	tree[root].flag5 = max(tree[root].flag5, max(tree[root << 1].flag5, tree[root << 1 | 1].flag5));
	tree[root].flag7 = max(tree[root].flag7, max(tree[root << 1].flag7, tree[root << 1 | 1].flag7));
}
inline ll query(int root, int l, int r)
{
	pushdown(root);
	if (l <= tree[root].l && tree[root].r <= r)
	{
		return max(max(tree[root].flag2, tree[root].flag3), max(tree[root].flag5, tree[root].flag7));
	}
	register int mid = (tree[root].l + tree[root].r) >> 1;
	if (mid >= r) return query(root << 1, l, r);
	else if (mid < l) return query(root << 1 | 1, l, r);
	else return max(query(root << 1, l, mid), query(root << 1 | 1, mid + 1, r));
}
int main()
{
	register int n, m;
	scanf("%d%d", &n, &m);
	build(1, 1, n);
	register char s[10];
	register int l, r;
	register ll val;
	while (m--)
	{
		scanf(" %s", s);
		scanf("%d%d", &l, &r);
		if (strcmp(s, "MULTIPLY") == 0)
		{
			scanf("%lld", &val);
			update(1, l, r, val);
		}
		else printf("ANSWER %lld\n", query(1, l, r));
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值