• 洛谷 P1121 环状最大两段子段和


    https://www.luogu.org/problemnew/show/P1121

    不会做啊。。。

    看题解讲的:

    答案的两段可能有两种情况:一是同时包含第1和第n个,2是不同时包含第1和第n个

    对于第二种可以先求出f[i],g[i]分别表示1..i和i..n的最大子段和,然后枚举断点解决

    对于第一种可以转化成找到“序列上最小两段字段和“去掉,这可以用第二种的方法解决;不过注意这个”序列上最小两段字段和“长度必须<=n-2(因为要剩下至少2个元素),需要一些特判

    另外,话说此题居然还能用线段树维护...

    (然而数据弱,仍然不知道以下代码是不是对的)

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<vector>
      5 using namespace std;
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 typedef long long ll;
     10 typedef unsigned long long ull;
     11 #define int ll
     12 struct pii
     13 {
     14     int fi,se;
     15     pii():fi(0),se(0){}
     16     pii(int a,int b):fi(a),se(b){}
     17 };
     18 pii max1(const pii &a,const pii &b)
     19 {
     20     return (a.fi<b.fi||(a.fi==b.fi&&a.se>b.se))?b:a;
     21 }
     22 pii min1(const pii &a,const pii &b)
     23 {
     24     return (a.fi<b.fi||(a.fi==b.fi&&a.se<b.se))?a:b;
     25 }
     26 int a[200010];
     27 pii f1[200010],g1[200010],f2[200010],g2[200010];
     28 int n,a1,a2,sum;
     29 int calc(int p)
     30 {
     31     if(p==1)
     32     {
     33         return g2[2].se==n-1 ? g2[2].fi-max(a[2],a[n]) : g2[2].fi;
     34     }
     35     else if(p==n)
     36     {
     37         return f2[n-1].se==n-1 ? f2[n-1].fi-max(a[1],a[n-1])
     38             : f2[n-1].fi;
     39     }
     40     else
     41     {
     42         return f2[p-1].se+g2[p+1].se==n-1
     43             ? f2[p-1].fi+g2[p+1].fi - max(max(a[1],a[p-1]),
     44                 max(a[p+1],a[n]))
     45             : f2[p-1].fi+g2[p+1].fi;
     46     }
     47 }
     48 signed main()
     49 {
     50     int i;pii t;
     51     scanf("%lld",&n);
     52     if(n<=1)    exit(-1);
     53     for(i=1;i<=n;++i)
     54     {
     55         scanf("%lld",&a[i]);
     56         sum+=a[i];
     57     }
     58     f1[1]=pii(a[1],1);
     59     t=pii(a[1],1);
     60     if(t.fi<=0)    t=pii(0,0);
     61     for(i=2;i<=n;++i)
     62     {
     63         t.fi+=a[i];++t.se;
     64         f1[i]=max1(f1[i-1],t);
     65         if(t.fi<=0)    t=pii(0,0);
     66     }
     67     g1[n]=pii(a[n],1);
     68     t=pii(a[n],1);
     69     if(t.fi<=0)    t=pii(0,0);
     70     for(i=n-1;i>=1;--i)
     71     {
     72         t.fi+=a[i];++t.se;
     73         g1[i]=max1(g1[i+1],t);
     74         if(t.fi<=0)    t=pii(0,0);
     75     }
     76     f2[1]=pii(a[1],1);
     77     t=pii(a[1],1);
     78     if(t.fi>=0)    t=pii(0,0);
     79     for(i=2;i<=n;++i)
     80     {
     81         t.fi+=a[i];++t.se;
     82         f2[i]=min1(f2[i-1],t);
     83         if(t.fi>=0)    t=pii(0,0);
     84     }
     85     g2[n]=pii(a[n],1);
     86     t=pii(a[n],1);
     87     if(t.fi>=0)    t=pii(0,0);
     88     for(i=n-1;i>=1;--i)
     89     {
     90         t.fi+=a[i];++t.se;
     91         g2[i]=min1(g2[i+1],t);
     92         if(t.fi>=0)    t=pii(0,0);
     93     }
     94     a1=f1[1].fi+g1[2].fi;
     95     for(i=2;i<=n-1;++i)
     96         a1=max(a1,f1[i].fi+g1[i+1].fi);
     97     a2=calc(1);
     98     for(i=2;i<=n;++i)
     99         a2=min(a2,calc(i));
    100     printf("%lld",max(a1,sum-a2));
    101     return 0;
    102 }
    View Code
  • 相关阅读:
    Linux I2C核心、总线和设备驱动
    移植 Linux 内核
    同步、互斥、阻塞
    异步通知
    poll机制
    Linux异常处理体系结构
    字符设备的驱动
    进程间的通信—套接字(socket)
    进程间的通信—信号量
    Spring事件的应用
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9861545.html
Copyright © 2020-2023  润新知