链接
https://codeforces.com/problemset/problem/1157/F
题解
首先用
a
i
a_i
ai表示大小为
i
i
i的数有多少个
可以发现,我其实就是找一段连续的
a
l
,
a
l
+
1
,
.
.
.
,
a
r
a_l,a_{l+1},...,a_r
al,al+1,...,ar使得它们的和最大而且必须满足当
i
∈
[
l
+
1
,
r
−
1
]
i\in[l+1,r-1]
i∈[l+1,r−1]时
a
i
>
1
a_{i}>1
ai>1
我先想了一个
d
p
dp
dp然后发现越写越麻烦
其实最后发现根本不用
d
p
dp
dp
考虑以
a
i
a_i
ai为结尾的合法序列,我显然可以贪心的把左端延长,只要这个序列中间的数字都
>
1
>1
>1就行,最左端的可以是
0
0
0可以是
1
1
1
那就很好办了,我搞一个
p
p
p指针,枚举右端时,如果经过了
1
1
1就让
p
p
p跳过来,否则
p
p
p只要原地呆在那里不动就好了
a
i
=
0
a_i=0
ai=0的时候我直接特殊处理,跳过就好了,同时注意更新一下
p
p
p
代码
#include <bits/stdc++.h>
#define eps 1e-8
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define cl(x) memset(x,0,sizeof(x))
#define mod 1000000007ll
#define maxn 300010
using namespace std;
typedef long long ll;
ll read(ll x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
ll n, a[maxn], ans[maxn], l[maxn], p1, p2, s[maxn], pos;
int main()
{
n=read();
for(auto i=1;i<=n;i++)a[read()]++;
for(auto i=1;i<maxn;i++)s[i]+=s[i-1]+a[i];
p1=p2=1;
for(p2=1;p2<maxn;p2++)
{
if(a[p2]==0)
{
p1=p2+1;
continue;
}
if(a[p2]>1)
{
ans[p2]=s[p2]-s[p1-1];
l[p2]=p1;
if(ans[p2]>ans[pos])pos=p2;
}
if(a[p2]==1)
{
ans[p2]=s[p2]-s[p1-1];
l[p2]=p1;
if(ans[p2]>ans[pos])pos=p2;
p1=p2;
}
}
printf("%lld\n",ans[pos]);
ll L=l[pos], R=pos;
for(auto i=L;i<=R;i++)printf("%lld ",i), a[i]--;
for(auto i=R;i>=L;i--)while(a[i]--)printf("%lld ",i);
return 0;
}