hdu 5869 - 树状数组 + 离线 + 离散(扩展)

解题思路:首先这题a[i]值最大1e6所以可以不用考虑离散化,但是为了方便数据扩大我强行再加了一个log(n)复杂度进行数据离散化。所以现在的复杂度应该是nlog(n)*log(n),不离散的话一个log(n)就可以了。

vec[i]数组保存保存区间右界为i的所有gcd情况和该gcd最后出现的位置,那么从i位置一直向左扫gcd肯定是会越来越小的或者不变,变小的话最少变小2倍,所以一个前缀gcd个数不会超过他的log(a[i])的个数。所以我们可以用nlog(n)处理出所有位置做右边界的gcd值和他的最后出现的位置。可以采用a[i]和vec[i-1]里面的数gcd就可以得到vec[i]

离散化:在gcd过大的情况下才使用

离线:将要查询的所有区间以r从小到大排序之后,从小到大考虑。更新vec[i]里面的gcd,如果里面的gcd有出现过,取消掉之前的位置,改换为现在的位置,因为现在的位置肯定包含之前的位置了(以i为右边界那么如果j位置能考虑到,那么j右边的位置也都能取到,所以以取最右边的为准)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,m,gcd[mx*18],a[mx],top,tot;
vector <pair<int,int>> vec[mx],q[mx];
//每个前缀i的gcd不同个数不会超过log(a[i]),因为gcd肯定最少是以2倍减少的 
int sum[mx],last[mx*18],ans[mx];
void add(int x,int v)
{
	while(x<=n){
		sum[x] += v;
		x += x&(-x);
	}
}
int get_sum(int x)
{
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值