HDU - 4630 No Pain No Game(离线线段树)
Posted mengx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 4630 No Pain No Game(离线线段树)相关的知识,希望对你有一定的参考价值。
No Pain No Game
题意:给出一个长度为n的1到n的排列 求区间两点gcd最大
思路:
因为题目没有更新 我们可以离线求解
对于每个查询按r排序
因为两点gcd一定会是两个数的约数 那么可以暴力插入a[i]的约数(当a[x]含有这个约数时 我们就能插入这个约数(x<i))
我们使用last数组维护上一次出现这个约数的位置即可
查询:我们就只需要查询l~r出现过最大的约数就行
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define inf 0x3f3f3f3f const int maxn = 50000+5; int Max[maxn<<2],a[maxn],last[maxn],ans[maxn]; struct node int l,r,id; bool friend operator<(const node u,const node v) return u.r<v.r; p[maxn]; void build(int l,int r,int rt) Max[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(lson); build(rson); void push_up(int rt) Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); void update(int l,int r,int rt,int L,int val) if(l==r) Max[rt]=max(Max[rt],val); return ; int m=(l+r)>>1; if(L<=m) update(lson,L,val); else update(rson,L,val); push_up(rt); int query(int l,int r,int rt,int L,int R) if(L<=l&&r<=R) return Max[rt]; int m=(l+r)>>1; int ans=0; if(L<=m) ans=max(ans,query(lson,L,R)); if(R>m) ans=max(ans,query(rson,L,R)); return ans; int main() int t,n,m; scanf("%d",&t); while(t--) scanf("%d",&n); memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d %d",&p[i].l,&p[i].r); p[i].id=i; sort(p+1,p+1+m); int j=1; build(1,n,1); for(int i=1;i<=n;i++) for(int k=1;k*k<=a[i];k++) if(a[i]%k==0) if(last[k]) update(1,n,1,last[k],k); if(last[a[i]/k]&&k!=a[i]/k) update(1,n,1,last[a[i]/k],a[i]/k); last[k]=i; last[a[i]/k]=i; while(p[j].r<=i) if(j>m) break; if(p[j].l>p[j].r) ans[p[j].id]=0; else ans[p[j].id]=query(1,n,1,p[j].l,p[j].r); j++; for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0;
以上是关于HDU - 4630 No Pain No Game(离线线段树)的主要内容,如果未能解决你的问题,请参考以下文章
hdu 4630 No Pain No Game 线段树离线处理
HDU - 4630 No Pain No Game(离线线段树)
hdu 4630 No Pain No Game (线段树+离线)