题目大意:给你一个无序的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. POJ 2018

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

  2. quick-cocos2dx 之transition.execute()的缓动效果

    注:本文图片来源(http://hosted.zeh.com.br/tweener/docs/en-us/misc/transitions.html. 侵权请告知,即刻删除) 什么是缓动, 缓动(ea ...

  3. Linux Unix shell 编程指南学习笔记(第三部分)

    第十三章  登陆环境 登陆系统时.输入username和password后.假设验证通过.则进入登录环境. 登录过程 文件/etc/passwd $HOME.profile 定制$HOME.profi ...

  4. CF 558C(Amr and Chemistry-构造法)

    C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard ...

  5. 2015.04.30,外语,读书笔记-《Word Power Made Easy》 14 “如何谈论日常现象” SESSION 40

    1. money, and what it will buy penury(['penjuri] n. 贫穷,拮据),来自拉丁词语penuria(need,needness的意思),主要指缺乏财富资源 ...

  6. 英语发音规则---V字母

    英语发音规则---V字母 一.总结 一句话总结: 1.V发[v]? voice [vɒɪs] n. 声音 love [lʌv] n. 恋爱 leave [liːv] vt. 离开 very ['ver ...

  7. UESTC--1263--The Desire of Asuna(贪心)

    The Desire of Asuna Time Limit: 1000MS   Memory Limit: 65535KB   64bit IO Format: %lld & %llu Su ...

  8. weblogic状态监控脚本

    echo "======================================welcome============================================ ...

  9. js 预加载图片image()函数

    创建一个Image对象:var a=new Image();    定义Image对象的src: a.src=”xxx.gif”;    这样做就相当于给浏览器缓存了一张图片. 图像对象: 建立图像对 ...

  10. Ubuntu16.04下沙盒数据导入到 Neo4j 数据库(图文详解)

    不多说,直接上干货! 参考博客 http://blog.csdn.net/u012318074/article/details/72793914   (表示感谢)  前期博客 Neo4j沙盒实验申请过 ...