HDU-4630(离线)

本博客主要探讨HDU-4630题目的解决方案,涉及全排列中区间内两个数字最大公约数(GCD)的查询。通过预处理数字的因子并按右端点排序询问,枚举数字因子并利用树状数组的后缀形式处理区间最值查询。同时对比了线段树和树状数组在解决此类问题上的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:HDU-4630
题意:1~n的全排列,多次询问区间内,两个数字gcd的最大值

预处理出一个数字的所有因子,如果一个因子出现两次以上说明可能作为答案。
对询问按照右端点排序。
按位置从小到大枚举,枚举该数字的所有因子,如果之前该因子出现过,则在该因子之前的位置处更新值为该因子。

如果要用线段树维护,那直接做就行。
如果要用树状数组维护,树状数组维护的是具有前缀性质的, [ l , r ] [l,r] [l,r]的最大值显然不能由 [ 1 , l − 1 ] [1,l-1] [1,l1] [ 1 , r ] [1,r] [1,r]得到,那这里用一个比较优秀的想法,因为我们对询问排序了,那按照位置更新,一定到查询的时候,更新过的位置都是<=当前位置的,那么我们可以将树状数组弄成后缀的形式,即可处理区间最值查询问题。一般情况下例如维护区间和,如果将一个位置加的话,是会对其之后的位置造成影响,这里是之前。

线段树

#include<bits/stdc++.h>
using namespace std;

const int maxn=5e4+7;

vector<int> v[maxn];

int maxx[maxn<<2|1];

void pushup(int k){
   
    maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}

void build(int l,int r,int k){
   
    maxx[k]=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
}

void updata(int l,int r,int k,int id,int val){
   
    if(l==r){
   
        maxx[k]=max(maxx[k],val);
        return ;
    }
    int mid=(l+r)>>1;
    if(id<=mid) updata(l,mid,</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值