HDU 4630 No Pain No Game (线段树+离线)
题目大意:给你一个无序的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 (线段树+离线)的更多相关文章
- HDU - 4630 No Pain No Game (线段树 + 离线处理)
id=45786" style="color:blue; text-decoration:none">HDU - 4630 id=45786" style ...
- hdu 4630 No Pain No Game 线段树离线处理
题目链接 求出一个区间内任意两个数的gcd的最大值. 先将询问读进来然后按r值排序. 将每一个数因数分解, 对每一个因子x, 如果pre[x]!=-1, 那么就更新update(pre[x], x, ...
- hdu 4630 No Pain No Game(线段树+离线操作)
No Pain No Game Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 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 ...
- E - No Pain No Game 线段树 离线处理 区间排序
E - No Pain No Game HDU - 4630 这个题目很好,以后可以再写写.这个题目就是线段树的离线写法,推荐一个博客:https://blog.csdn.net/u01003321 ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模
Multiply game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- 线段树+离线 hdu5654 xiaoxin and his watermelon candy
传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...
随机推荐
- [luogu4107 HEOI2015] 兔子与樱花(树形dp+贪心)
传送门 Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个 ...
- [luogu3203 HNOI2010] 弹飞绵羊 (分块)
传送门 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置, ...
- NFS学习
linux下搭建nfs服务: NFS是network filesystem的缩写,它可以通过网络,让不同的机器.不同的操作系统共享文件. NFS支持的功能比较多,默认端口也是随机的,基于远程调用服务( ...
- linux双网卡配置
一.VM虚拟机添加一个网络适配器. 选择自己需要的模式类型 二.启动虚拟机,配置网卡 按原先配置网卡的方式配置完(ip地址及默认网关还有网卡名不能跟原先的一样) 重启所有网卡(service netw ...
- 不引用第三方变量交换a和b的值
方法一:(可操作字符) a = a^b; b = a^b; a = a^b; 方法二:(可操作字符) a=a+b; b=a-b; a=a-b; 方法三:(不可以操作字符) a=a*b; b=a/b; ...
- Python包结构和函数式编程
# 包的结构 |--包 |--|-- __init__.py 包的标志文件 |--|-- 模块1 |--|-- 模块2 |--|-- 子包(子文件夹) |--|--|-- __init__.py 包的 ...
- ES scroll(ES游标) 解决深分页
ES scroll(ES游标) 解决深分页. Why 当Elasticsearch响应请求时,它必须确定docs的顺序,排列响应结果.如果请求的页数较少(假设每页20个docs), Elasticse ...
- BA-通讯总线-百通1419a和9841
百通1419A线缆的简单介绍: Belden1419A- Belden电缆线1419A 多股导体—低容计算机电缆 FOR EIA RS-232/422 Belden 1419A是24 AWG(7*32 ...
- oracle常见sql语句优化
1.* 号引起的运行效率 尽量降低使用select * 来进行查询,当你查询使用*, 数据库会进行解析并将*转换为所有列. select count(si.student_id) from Stud ...
- python 并发编程入门
多进程 在Unix/Linux下,为我们提供了类似c中<unistd.h>头文件里的的fork()函数的接口,这个函数位于os模块中,相同与c中类似,对于父进程fork()调用返回子进程I ...