题目大意:给你一个无序的1~n的排列a,每次询问[l,r]之间任取两个数得到的最大gcd是多少

先对所有询问离线,然后把问题挂在区间的左端点上(右端点也行)

在预处理完质数,再处理一个next数组,表示 i 的任意一个质因子,这样我们分解质因数的时间降低到而不是

因为能对答案产生贡献的都是成对出现的两个数

所以每次记录一个last[i],表示数 i 上一次出现的位置

当遍历到第 i 个数时,分解出它的所有质因数,然后搜出它所有的因子,因子个数大约不会超过,均摊下来就更少了

那么,a[i] 的某个因数 x 就能和 last[x]成为一对,在线段树里的last[x]位置更新答案,即gcd(a[i],a[last[x]]),但不一定是last[x]的最优解,要在last[x]的位置取一个max

询问就是线段树里查询[l,r]的最大值

 #include <cstdio>
#include <algorithm>
#include <cstring>
#define N 50010
#define M 50
#define ll long long
using namespace std; int n,q,cte,num,nson,T;
int a[N],pr[N],nxt[N],use[N],head[N];
int son[N],d[N],app[N],pw[N],la[N];
struct node{int l,r,id,ans;}Q[N];
struct Edge{int to,nxt;}edge[N];
void ae(int u,int v){
cte++;edge[cte].to=v;edge[cte].nxt=head[u];head[u]=cte;}
int gcd(int x,int y){if(y==)return x;return gcd(y,x%y);}
struct Seg{
#define il inline
int ma[N<<];
il void pushup(int rt){ma[rt]=max(ma[rt<<],ma[rt<<|]);}
void build(int l,int r,int rt)
{
if(l==r) {ma[rt]=;return;}
int mid=(l+r)>>;
build(l,mid,rt<<),build(mid+,r,rt<<|);
pushup(rt);
}
void update(int x,int l,int r,int rt,int w)
{
if(l==r){ma[rt]=max(ma[rt],gcd(w,a[l]));return;}
int mid=(l+r)>>;
if(x<=mid) update(x,l,mid,rt<<,w);
else update(x,mid+,r,rt<<|,w);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R){return ma[rt];}
int mid=(l+r)>>,ans=;
if(L<=mid) ans=max(query(L,R,l,mid,rt<<),ans);
if(R>mid) ans=max(query(L,R,mid+,r,rt<<|),ans);
return ans;
}
#undef il
}seg;
int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=(ret<<)+(ret<<)+c-'';c=getchar();}
return ret*fh;
}
void get_pr()
{
int cnt=;
for(int i=;i<N;i++){
if(!use[i]) pr[++cnt]=i,nxt[i]=i;
for(int j=;j<=cnt&&i*pr[j]<N;j++){
use[i*pr[j]]=,nxt[i*pr[j]]=pr[j];
if(i%pr[j]==) break;
}
}
}
void Div(int x){
num=;int p;
while(x!=){
num++;p=son[num]=nxt[x];d[num]=;
while(x%p==) x/=p,d[num]++;
}
}
void dfs_ap(int k){
if(k==num+){
app[++nson]=;
for(int i=;i<=num;i++)
app[nson]*=pw[i];
return;}
pw[k]=;
for(int j=;j<=d[k];j++)
dfs_ap(k+),pw[k]*=son[k];
}
void solve(int k)
{
Div(a[k]);nson=;dfs_ap();
for(int i=;i<=nson;i++)
{
if(!la[app[i]]) la[app[i]]=k;
else{
seg.update(la[app[i]],,n,,app[i]);
la[app[i]]=k;
}
}
for(int j=head[k];j;j=edge[j].nxt){
int v=edge[j].to;
Q[v].ans=seg.query(Q[v].l,Q[v].r,,n,);
}
}
void init()
{
for(int i=;i<=n;i++)
a[i]=use[N]=head[i]=la[i]=;
for(int i=;i<=q;i++)
Q[i].l=Q[i].r=Q[i].ans=edge[i].to=edge[i].nxt=;
memset(&seg,,sizeof(seg));
cte=;
}
int main()
{
scanf("%d",&T);
get_pr();
for(int t=;t<=T;t++)
{
scanf("%d",&n);
for(int i=;i<=n;i++)
a[i]=gint();
scanf("%d",&q);
for(int i=;i<=q;i++)
Q[i].l=gint(),Q[i].r=gint(),ae(Q[i].l,i);
seg.build(,n,);
for(int i=n;i>=;i--)
solve(i);
for(int i=;i<=q;i++){
if(Q[i].l==Q[i].r) Q[i].ans=;
printf("%d\n",Q[i].ans);
}init();
}
return ;
}

HDU 4630 No Pain No Game (线段树+离线)的更多相关文章

  1. HDU - 4630 No Pain No Game (线段树 + 离线处理)

    id=45786" style="color:blue; text-decoration:none">HDU - 4630 id=45786" style ...

  2. hdu 4630 No Pain No Game 线段树离线处理

    题目链接 求出一个区间内任意两个数的gcd的最大值. 先将询问读进来然后按r值排序. 将每一个数因数分解, 对每一个因子x, 如果pre[x]!=-1, 那么就更新update(pre[x], x, ...

  3. hdu 4630 No Pain No Game(线段树+离线操作)

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  4. HDU 4630 No Pain No Game 线段树 和 hdu3333有共同点

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  5. E - No Pain No Game 线段树 离线处理 区间排序

    E - No Pain No Game  HDU - 4630 这个题目很好,以后可以再写写.这个题目就是线段树的离线写法,推荐一个博客:https://blog.csdn.net/u01003321 ...

  6. hdu 5274 Dylans loves tree(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  7. HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模

    Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  8. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

  9. 线段树+离线 hdu5654 xiaoxin and his watermelon candy

    传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...

随机推荐

  1. 指针FHQTreap

    不太友好的代码 题面依旧是普通平衡树 //Writer : Hsz %WJMZBMR%tourist%hzwer #include <bits/stdc++.h> #define LL l ...

  2. 园区IP地址规划(非常详细)

    转:https://mp.weixin.qq.com/s/Zlm7x5eunIYLAG7Sp0yVCQ 经过这些年工作,接触从几万.几十万到上亿的项目都有: 我简单总结了接触的大部分的项目,将园区网核 ...

  3. 接口(interface) 可以 new()吗???~

    比如 一个接口 A ,里面有一个方法fun1(),一般我们是先定义它的实现再引用它,比如 public class ImpA implements A{ public void fun1(){ //d ...

  4. POJ 2018

    又一水,设dp[i]为以i结尾的有最大平均值的起始位置. #include <iostream> #include <cstdio> #include <cstring& ...

  5. [Angular] Upgrade existing Angular app to Progressive Web App

    If you alread have an existing Angular application and want to upgrade to progressive web app. 1. In ...

  6. Java设计模式透析之 —— 模板方法(Template Method)

    今天你还是像往常一样来上班,一如既往地開始了你的编程工作. 项目经理告诉你,今天想在server端添加一个新功能.希望写一个方法.能对Book对象进行处理.将Book对象的全部字段以XML格式进行包装 ...

  7. 怎样使用 CCache 进行 cocos2d-x 编译加速

    https://github.com/chukong/cocos-docs/blob/master/manual/framework/native/v3/ccache-speed-up/zh.md C ...

  8. mysqlbinlog高速遍历搜索记录

    目标,开发者说有个数据莫名其妙加入了.可是不知道是从哪里加入的.并且应用功能里面不应该加入这种数据,为了查清楚来源,所以我就准备去binlog里面找了.可是binlog有好几个月的数,我这样一个个my ...

  9. [MySQL] 统计函数记录

    时间段统计========== 按年汇总,统计:select sum(mymoney) as totalmoney, count(*) as sheets from mytable group by ...

  10. [Tomcat]Tomcat安全设置

    1.关闭服务器端口:server.xml默认有下面一行: <Server port="8005" shutdown="SHUTDOWN"> 这样允许 ...