CCF-CSP-201709-5:除法

问题描述

解题思路

       看题目,开始以为是考察线段树。但是仔细思考之后发现,根据区间的操作“所有v的倍数除以v”无法对现有的区间状态“和(Sum)”进行更新。因此线段树的LazyTag和区间状态都失效了。
       改用树状数组做,对每个点进行更新。根据数据量,可能会超时。试了一下,果不其然TLE。
       没有了思路,参考ccf 201709-5 除法,对上述树状数组进行了两点的优化,就不超时了。
       只能说,这题的数据有点玄学。

AC代码

#include <iostream>

using namespace std;

constexpr auto MaxSize = 100010;

using LL = long long int;

int NumSet[MaxSize] = { 0 };
LL BinaryIndexedTree[MaxSize] = { 0 };

inline int Lowbit(int x) { return x & (-x); }

LL GetSum(int Index)
{
	LL Sum = 0;

	while (Index > 0)
	{
		Sum += BinaryIndexedTree[Index];
		Index -= Lowbit(Index);
	}
	
	return Sum;
}

void Update(int Index, int N, int Num)
{
	while (Index <= N)
	{
		BinaryIndexedTree[Index] += Num;
		Index += Lowbit(Index);
	}
}

void Update(int Left,int Right, int N, int Divisor)
{
	for (int Index = Left; Index <= Right; ++Index)
	{
		//玄学优化1
		if (NumSet[Index] >= Divisor && NumSet[Index] % Divisor == 0)
		{
			int Lose = NumSet[Index] - NumSet[Index] / Divisor;
			NumSet[Index] -= Lose;

			Update(Index, N, -Lose);
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	int N, OPNum;

	cin >> N >> OPNum;

	for (int i = 1; i <= N; ++i)
	{
		cin >> NumSet[i];
		Update(i, N, NumSet[i]);
	}

	for (int i = 0; i < OPNum; ++i)
	{
		int OPCode, Left, Right, Divisior;
		cin >> OPCode >> Left >> Right;

		if (OPCode == 1)
		{
			cin >> Divisior;
			if (Divisior == 1) continue;	//玄学优化2
			Update(Left, Right, N, Divisior);
		}
		else
		{
			cout << GetSum(Right) - GetSum(Left - 1) << endl;
		}
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值