• [hdu4630] No Pain No Game


    某次模拟赛的T1。

    刚开始怀疑是RMQ......我真是太弱了QAQ

    题目传送门

    正解是离线操作,把所有询问按r从小到大排序。

    然后把数从左到右处理,处理完第i个数,就可以回答所有r==i的询问了。

    分解因数,记录下来每个因数上一次出现的位置。

    又遇到这个因数,就把上一次的位置加进线段树,把这一次的位置记录下来。

    这样线段树里有这个数当且仅当这个数出现了两次以上。

    此时这个数显然是备选的合法答案之一,然后询问的时候询问区间最大值就行了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int t;
     7 int n,m;
     8 int a[50005];
     9 int pre[50005];
    10 
    11 struct query
    12 {
    13     int ql,qr,ans,id;
    14     void get(){scanf("%d%d",&ql,&qr);}
    15 }q[50005];
    16 
    17 int cmp(query w,query e){return w.qr<e.qr;}
    18 int cmpb(query w,query e){return w.id<e.id;}
    19 
    20 int mx[200005],lb[200005],rb[200005];
    21 
    22 void build(int p,int l,int r)
    23 {
    24     lb[p]=l,rb[p]=r,mx[p]=-1;
    25     if(l==r)return;
    26     int mid=(l+r)>>1;
    27     build(p<<1,l,mid);
    28     build(p<<1|1,mid+1,r);
    29 }
    30 
    31 void pushup(int p)
    32 {
    33     mx[p]=max(mx[p<<1],mx[p<<1|1]);
    34 }
    35 
    36 void change(int p,int pos,int val)
    37 {
    38     if(lb[p]==rb[p])
    39     {
    40         mx[p]=max(mx[p],val);
    41         return;
    42     }
    43     int mid=(lb[p]+rb[p])>>1;
    44     if(pos<=mid)change(p<<1,pos,val);
    45     else change(p<<1|1,pos,val);
    46     pushup(p);
    47 }
    48 
    49 int ask(int p,int l,int r)
    50 {
    51     if(l<=lb[p]&&r>=rb[p])return mx[p];
    52     int ret=-1,mid=(lb[p]+rb[p])>>1;
    53     if(l<=mid)ret=max(ask(p<<1,l,r),ret);
    54     if(r>mid)ret=max(ask(p<<1|1,l,r),ret);
    55     return ret;
    56 }
    57 
    58 void work()
    59 {
    60     scanf("%d",&n);
    61     build(1,1,n);
    62     memset(pre,0,sizeof(pre));
    63     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    64     scanf("%d",&m);
    65     for(int i=1;i<=m;i++)q[i].get(),q[i].id=i;
    66     sort(q+1,q+m+1,cmp);
    67     int nw=1;
    68     for(int i=1;i<=n;i++)
    69     {
    70         for(int k=1;k*k<=a[i];k++)
    71         {
    72             if(a[i]%k)continue;
    73             if(pre[k])change(1,pre[k],k);
    74             if(pre[a[i]/k]&&a[i]!=k*k)
    75                 change(1,pre[a[i]/k],a[i]/k);
    76             pre[k]=pre[a[i]/k]=i;
    77         }
    78         while(q[nw].qr==i)
    79         {
    80             if(q[nw].ql>=q[nw].qr)q[nw].ans=0;
    81             else q[nw].ans=ask(1,q[nw].ql,q[nw].qr);
    82             nw++;
    83         }
    84     }
    85     sort(q+1,q+m+1,cmpb);
    86     for(int i=1;i<=m;i++)printf("%d
    ",q[i].ans);
    87 }
    88 
    89 int main()
    90 {
    91     scanf("%d",&t);
    92     while(t--)work();
    93     return 0;
    94 }
  • 相关阅读:
    C#笔记(Hex转JPG)
    rpm 和 yum 软件管理
    名称空间和作用域
    网络技术管理和进程管理
    RAID磁盘阵列
    CentOS7系统启动流程:
    磁盘lvm管理
    面向对象 异常处理
    自定义函数和调用函数 return返回值
    Python常用模块
  • 原文地址:https://www.cnblogs.com/cervusy/p/9794577.html
Copyright © 2020-2023  润新知