【HDU5869】Different GCD Subarray Query(求[L,R]内有多少个不同的区间gcd---树状数组+思维)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5869

题目:


给定序列和要查询的区间[L,R],求[L,R]内有多少个不同的区间gcd

 

解题思路:


(1)遍历序列,预处理出以a[i]为结尾的区间的gcd并记录,注意,有多个以a[i]为结尾的区间gcd相同,取左边界最大的那个,这样在用线段树求不同区间gcd的数目时,就避免了-1和+1的更新,节省时间和空间。为了取左边界最大的那个,可以倒序处理,即依次求[i,i] [i-1,i] [i-2,i]...[1,i]的区间gcd,如果当前求的gcd和上次求的gcd相同,则不更新这个gcd对应的左边界。

尝试自己写代码遇到的问题:不能用map<int,int> gd[maxn],因为map自动按照key值从小到大排序,影响结果,可以用pair和vector。此外,也不能用map中的key来存【x,i】的左边界x,如果这样的话在预处理时实践复杂度就达到了(n+1)*n/2, 会超时。

正确的处理方法:

vector<pair<int, int> > gd[maxn];//gd[i]中记录的是以a[i]为末尾的所有的gcd,<key,value>,表示【value,i】的区间gcd为key
void getIntervalGcd()
{
    for(int i = 1; i 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值