hdu 4630 No Pain No Game (线段树+离线)

Posted guapisolo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]的最大值

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #define N 50010
  5 #define M 50
  6 #define ll long long 
  7 using namespace std;
  8 
  9 int n,q,cte,num,nson,T;
 10 int a[N],pr[N],nxt[N],use[N],head[N];
 11 int son[N],d[N],app[N],pw[N],la[N];
 12 struct node{int l,r,id,ans;}Q[N];
 13 struct Edge{int to,nxt;}edge[N];
 14 void ae(int u,int v){
 15 cte++;edge[cte].to=v;edge[cte].nxt=head[u];head[u]=cte;}
 16 int gcd(int x,int y){if(y==0)return x;return gcd(y,x%y);}
 17 struct Seg{
 18     #define il inline
 19     int ma[N<<2];
 20     il void pushup(int rt){ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);}
 21     void build(int l,int r,int rt)
 22     {
 23         if(l==r) {ma[rt]=1;return;}
 24         int mid=(l+r)>>1;
 25         build(l,mid,rt<<1),build(mid+1,r,rt<<1|1);
 26         pushup(rt);
 27     }
 28     void update(int x,int l,int r,int rt,int w)
 29     {
 30         if(l==r){ma[rt]=max(ma[rt],gcd(w,a[l]));return;}
 31         int mid=(l+r)>>1;
 32         if(x<=mid) update(x,l,mid,rt<<1,w);
 33         else update(x,mid+1,r,rt<<1|1,w);
 34         pushup(rt);
 35     }
 36     int query(int L,int R,int l,int r,int rt)
 37     {
 38         if(L<=l&&r<=R){return ma[rt];}
 39         int mid=(l+r)>>1,ans=0;
 40         if(L<=mid) ans=max(query(L,R,l,mid,rt<<1),ans);
 41         if(R>mid) ans=max(query(L,R,mid+1,r,rt<<1|1),ans);
 42         return ans;
 43     }
 44     #undef il
 45 }seg;
 46 int gint()
 47 {
 48     int ret=0,fh=1;char c=getchar();
 49     while(c<0||c>9){if(c==-)fh=-1;c=getchar();}
 50     while(c>=0&&c<=9){ret=(ret<<3)+(ret<<1)+c-0;c=getchar();}
 51     return ret*fh;
 52 }
 53 void get_pr()
 54 {
 55     int cnt=0;
 56     for(int i=2;i<N;i++){
 57         if(!use[i]) pr[++cnt]=i,nxt[i]=i;
 58         for(int j=1;j<=cnt&&i*pr[j]<N;j++){
 59             use[i*pr[j]]=1,nxt[i*pr[j]]=pr[j];
 60             if(i%pr[j]==0) break;
 61         }
 62     }
 63 }
 64 void Div(int x){
 65     num=0;int p;
 66     while(x!=1){
 67         num++;p=son[num]=nxt[x];d[num]=0;
 68         while(x%p==0) x/=p,d[num]++;
 69     }
 70 }
 71 void dfs_ap(int k){
 72     if(k==num+1){
 73         app[++nson]=1;
 74         for(int i=1;i<=num;i++) 
 75             app[nson]*=pw[i];
 76         return;}
 77     pw[k]=1;
 78     for(int j=0;j<=d[k];j++)
 79         dfs_ap(k+1),pw[k]*=son[k];
 80 }
 81 void solve(int k)
 82 {
 83     Div(a[k]);nson=0;dfs_ap(1);
 84     for(int i=1;i<=nson;i++)
 85     {
 86         if(!la[app[i]]) la[app[i]]=k;
 87         else{
 88             seg.update(la[app[i]],1,n,1,app[i]);
 89             la[app[i]]=k;
 90         }
 91     }
 92     for(int j=head[k];j;j=edge[j].nxt){
 93         int v=edge[j].to;
 94         Q[v].ans=seg.query(Q[v].l,Q[v].r,1,n,1);
 95     }
 96 }
 97 void init()
 98 {
 99     for(int i=1;i<=n;i++)
100         a[i]=use[N]=head[i]=la[i]=0;
101     for(int i=1;i<=q;i++)
102         Q[i].l=Q[i].r=Q[i].ans=edge[i].to=edge[i].nxt=0;
103     memset(&seg,0,sizeof(seg));
104     cte=0;
105 }
106 int main()
107 {
108     scanf("%d",&T);
109     get_pr();
110     for(int t=1;t<=T;t++)
111     {
112         scanf("%d",&n);
113         for(int i=1;i<=n;i++)
114             a[i]=gint();
115         scanf("%d",&q);
116         for(int i=1;i<=q;i++)
117             Q[i].l=gint(),Q[i].r=gint(),ae(Q[i].l,i);
118         seg.build(1,n,1);
119         for(int i=n;i>=1;i--)
120             solve(i);
121         for(int i=1;i<=q;i++){
122             if(Q[i].l==Q[i].r) Q[i].ans=0;
123             printf("%d
",Q[i].ans);
124         }init();
125     }
126     return 0;
127 }

 

以上是关于hdu 4630 No Pain No Game (线段树+离线)的主要内容,如果未能解决你的问题,请参考以下文章

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

HDU - 4630 No Pain No Game(离线线段树)

hdu 4630 No Pain No Game (线段树+离线)

E - No Pain No Game 线段树

迟来的2021年终总结,2022已开始,Good luck every one! No pain No gain!

Python--关于 join 和 split