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],问区间里有多少个三元组满足 ...
随机推荐
- webpack学习笔记(2)--webpack.config.js
3 模式 mode mode 参数设置为 development(开发模式), production(生产模式) 或 none(无),可以启用对应环境下 webpack 内置的优化.默认值为 prod ...
- POJ3984-迷宫问题【BFS】
定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, ...
- EhCache缓存页面、局部页面和对象缓存
页面缓存:SimplePageCachingFilter web.xml <!-- 页面缓存配置,配合ehcache.xml中name为“SimplePageCachingFilter”(默认值 ...
- C#强化系列:HttpModule,HttpHandler,HttpHandlerFactory简单使用
这三个对象我们在开发Asp.net程序时经常会用到,似乎很熟悉,但有时候又不太确定.本文通过一个简单的例子来直观的比较一下这三个对象的使用.HttpModule:Http模块,可以在页面处理前后.应用 ...
- windowbuilder01 按钮事件监听
- String 基本使用方法, 以及要注意的事项
package chengbaoDemo; public class Test01 { public static void main(String[] args) { //字符串的两种创建形式 St ...
- BA-siemens-BA模块特性
PXC24(包含UEC24的模块特性) DO点可以接220vac的电压,渠道人员告知电流不要超过2A AO点只能输出0-10V的电压,不能输出4-20ma的电流,说明书上是错误的 AO点输出10v失败 ...
- Windows-命令窗口-强制关机命令
Windows +R CMD 命令行窗口shutdown -s -f -t 以上参数中的-s代表关机,-f表示强制关闭所有应用程序,-t 00代表不用等待立即执行(时间以秒计算,把时间改长就变成了定 ...
- spring容器启动过程理解
一.一切从手动启动IoC容器开始 ClassPathResource resource = new ClassPathResource("bean.xml"); DefaultLi ...
- Zookeeper源代码编译为Eclipseproject(win7下Ant编译)
为了深入学习ZooKeeper源代码,首先就想到将其导入到Eclispe中,所以要先将其编译为Eclispeproject. 1.什么是Ant??? Apache Ant™ Apache Ant is ...