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

题目大意:给你一个无序的1~n的排列a,每次询问[l,r]之间任取两个数得到的最大gcd是多少

先对所有询问离线,然后把问题挂在区间的左端点上(右端点也行)

在预处理完质数,再处理一个next数组,表示 i 的任意一个质因子,这样我们分解质因数的时间降低到O(logn)而不是O(sqrt{n})

因为能对答案产生贡献的都是成对出现的两个数

所以每次记录一个last[i],表示数 i 上一次出现的位置

当遍历到第 i 个数时,分解出它的所有质因数,然后搜出它所有的因子,因子个数大约不会超过O(log^2n),均摊下来就更少了

那么,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 }
原文地址:https://www.cnblogs.com/guapisolo/p/9768605.html