zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    .net core 基于IIS发布
    所有开源播放器
    JWT的相关讲解
    .NET Core2.0 使用EF做数据操作
    任意的组合,数组或数组,数组或list,list或list不用循环得出匹配的总数和需要的字段列
    linq to sql学习
    winform文本框怎么实现html的placeholder效果
    [数据结构]-单链表实现栈
    [数据结构]-数组实现栈
    [数据结构]-单链表
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9768605.html
Copyright © 2011-2022 走看看