zoukankan      html  css  js  c++  java
  • [LUOGU]P5502 [JSOI2015]最大公约数

    传送门

    题意:给一个序列a[1],a[2],a[3]...a[n],求其中连续的子序列A[L],A[L+1],...,A[R],使其权值 W(L,R)=(R-L+1)×gcd(A[L],...,A[R])最大。

    思路:

    简单的一个分治思想。

    先想想线段树里询问怎么做的?

    是不是把这个区间从中间砍开。然后丢到左/右儿子那里再问。

    同样的,在这里,对于所要求的ans区间

    也是可以 劈开 讨论的

    ·ans区间全在当前区间(l,r) 的右侧(l,mid);

    ·ans区间全在当前区间(l,r) 的左侧(mid+1,r);

    ·ans区间横跨左右儿子;

    对前俩种,直接往下递归就行。

    第三种,枚举一遍整个(l,r)区间,找到含有a[mid]的最大权值区间就行。此处复杂度约O(n).

    p.s.第三种情况可以从mid开始向两边拓展。


    OVER.

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define re register
     4 #define LL long long
     5 #define DB double
     6 #define For(x,a,b) for(re int x=a;x<=b;x++)
     7 #define For2(x,a,b) for(re int x=a;x>=b;x--)
     8 #define LFor(x,a,b) for(re LL x=a;x<=b;x++)
     9 #define LFor2(x,a,b) for(re LL x=a;x>=b;x--)
    10 #define Abs(x) ((x>0)? x:-x)
    11 int gi()
    12 {
    13     int res=0,fh=1;char ch=getchar();
    14     while((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
    15     if(ch=='-') fh=-1,ch=getchar();
    16     while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();
    17     return fh*res;
    18 }
    19 LL gl()
    20 {
    21     LL res=0,fh=1;char ch=getchar();
    22     while((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
    23     if(ch=='-') fh=-1,ch=getchar();
    24     while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();
    25     return fh*res;
    26 }
    27 int n;
    28 LL a[100005],ans;
    29 LL gcd(LL x,LL y) {return y==0? x:gcd(y,x%y);}
    30 LL deal(int l,int r,int L,int R)
    31 {
    32     LL _gcd=a[l],val=a[l],f=l;
    33     while(L<l&&r<R)
    34     {
    35         _gcd=gcd(_gcd,a[l-1]);
    36         l--;
    37         while(r<=R&&a[r]%_gcd==0) r++;
    38         while(L<=l&&a[l]%_gcd==0) l--;
    39         val=val<(LL)(r-l-1)*_gcd? (LL)(r-l-1)*_gcd:val;
    40         l++,r--;
    41     }
    42     l=r=f;
    43     _gcd=a[r];
    44     while(L<l&&r<R)
    45     {
    46         _gcd=gcd(_gcd,a[r+1]);
    47         r++;
    48         while(L<=l&&a[l]%_gcd==0) l--;
    49         while(r<=R&&a[r]%_gcd==0) r++;
    50         val=val<(LL)(r-l-1)*_gcd? (LL)(r-l-1)*_gcd:val;
    51         l++,r--;
    52     }
    53     return val;
    54 }
    55 LL dfs(int l,int r)
    56 {
    57     if(l==r) return a[l];
    58     int mid=l+r>>1;
    59     LL opt1=deal(mid,mid,l,r);
    60     LL opt2=dfs(l,mid);
    61     LL opt3=dfs(mid+1,r);
    62     return max(opt1,max(opt2,opt3));
    63 }
    64 
    65 int main()
    66 {
    67     n=gi();
    68     For(i,1,n) a[i]=gl();
    69     printf("%lld
    ",dfs(1,n));
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    Linux的僵尸进程及其解决方法
    描述linux系统从开机到登陆界面的启动过程
    __weak、__strong这样的关键词和weak、strong有哪些区别
    选择器(UIPickerView)
    UITableView 滚动流程性优化
    几种设置UITableView的cell动态高度的方法
    强大的Core Image(教你做自己的美图秀秀))
    iOS UIBezierPath类 介绍
    Quartz 2D编程指南- PDF文档的创建、显示及转换
    Quartz 2D编程指南(4) - 颜色和颜色空间
  • 原文地址:https://www.cnblogs.com/3soon/p/11536234.html
Copyright © 2011-2022 走看看