zoukankan      html  css  js  c++  java
  • 数字对

    https://zybuluo.com/ysner/note/1153362

    题面

    她的面前浮现出一个长度为(n)的序列({ai}),她想找出一段区间([L,R])((1leq L leq Rleq n))。
    这个特殊区间满足,存在一个(k)((Lleq kleq R)),并且对于任意的(i)((Lleq i leq R)),(a_i)都能被(a_k)整除。这样的一个特殊区间([L,R])价值为(R-L)
    (H)想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些
    区间又分别是哪些呢?

    • (30pts) (nleq30)
    • (60pts) (nleq3000)
    • (80pts) (nleq300000)
    • (100pts) (nleq500000)
    • (2s)时限

    解析

    • (30pts)算法

    • (60pts)算法

    线段树暴力维护(gcd)(max),二分最大长度,复杂度(O(nlog^2n))

    • (80pts)算法

    改为用(ST)表维护

    • (100pts)算法

    线段树求(gcd)算法???

    或者
    枚举中间点往两边拓展,遇到不能被整除的数就停。
    同时注意到被扩展到的数无需再次拓展。
    由于一点最多被拓展到两次,复杂度(O(2n))

    于是一道傻逼题就被暴力AC了)

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    #define re register
    #define il inline
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int N=5e5+100;
    int n,a[N],l,r,tot,ans=0,sol[N],cnt,now;
    bool vis[N];
    il int gi()
    {
      re int x=0,t=1;
      re char ch=getchar();
      while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    il void wri(re int x)
    {
      if(x<0) putchar('-'),x=-x;
      if(x>9) wri(x/10);
      putchar(x%10+'0');
    }
    il void work(re int i)
    {
      if(vis[i]) return;vis[i]=1;
          l=r=i;
          while(l>1)
    	{
    	  l--;
    	  if(a[l]%a[i]!=0) {l++;break;}
    	  else vis[l]=1;
    	}
          while(r<n)
    	{
    	  r++;
    	  if(a[r]%a[i]!=0) {r--;break;}
    	  else vis[r]=1;
    	}
          if(ans<r-l) ans=r-l,sol[tot=1]=l;
          else if(ans==r-l) sol[++tot]=l;
    }
    int main()
    {
      freopen("pair.in","r",stdin);
      freopen("pair.out","w",stdout);
      n=gi();
      tot=n;fp(i,1,n) sol[i]=i;
      fp(i,1,n) a[i]=gi();
      if(n>3000)
        {
          re int gaoshi=min((1e8/n),(n+100));
          fp(i,1,gaoshi-1) work(n/gaoshi*i);
          }
      fp(i,1,n) work(i);
      sort(sol+1,sol+1+tot);re int ysn=0;//printf("%d
    ",tot);
      fp(i,1,tot) if(sol[i]==sol[i-1]) ysn++;
      printf("%d %d
    ",tot-ysn,ans);
      fp(i,1,tot) if(sol[i]!=sol[i-1]) printf("%d ",sol[i]);
      printf("
    ");
      fclose(stdin);
      fclose(stdout);
      return 0;
    }
    
  • 相关阅读:
    SQL语句建表、设置主键、外键、check、default、unique约束
    郝斌老师的SQL教程
    Hello WPF!
    指针
    穷举法破解 zebrone1.1
    一条汇编指令引发的 蝴蝶效应 (后记)
    浮点 汇编指令基础知识
    收敛数列极限唯一性证明
    MFC SkinMagic使用方法
    Python初学1
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9060931.html
Copyright © 2011-2022 走看看