题目:
https://codeforces.com/contest/1157/problem/F
给出一个序列 , 我们要从序列里面挑出一些数构造成一个相邻元素之间绝对值为小于1的最大环 , 挑选的数不要求连续
分析:
不要求连续 , 我们可以先排个小序
对于一个满足条件的环我们可以这样的构造 : al , al+1 , al+2 .... ar , ar-1 , ar-2 ,...al+1
因为这样肯定是一个满足条件的结构 , 即:除了 al,aral,ar 之外的其他所有值应该都有至少两个。因此,开一个桶记录一下每个元素出现的次数,并对原序列进行去重 ; 我们还发现对于1 2 3 2 , 在1...2 这里面添加2的个数是没有什么影响的;使用双指针法,每次都找到 1 出现的位置,统计答案并更新答案即可。

#include<bits/stdc++.h> using namespace std; int n; int a[200001]; int cnt[200001]; int tot; int main() { scanf("%d",&n); for(int i=1 ; i<=n ; i++) { scanf("%d",&a[i]); cnt[a[i]]++; } sort(a+1,a+1+n); tot=unique(a+1,a+1+n)-(a+1); int ans=cnt[a[1]] , head=1 , tail=1; int anshead=1,anstail=1; while(head<=tot) { tail=head+1; int sum=cnt[a[head]]; while(tail<=tot && a[tail]-a[tail-1]==1 && cnt[a[tail]]>=2) { sum+=cnt[a[tail]]; tail++; } int cr=tail-1; if(tail<=tot&&a[tail]-a[tail-1]==1) sum+=cnt[a[tail]],cr=tail; if(sum>ans) { ans=sum; anshead=head; anstail=cr; } head=tail; } printf("%d ",ans); for(int i=1 ; i<=cnt[a[anshead]];i++)printf("%d ",a[anshead]); for(int i=anshead+1 ; i<anstail ; i++) { for(int j=1 ; j<cnt[a[i]];j++) printf("%d ",a[i]); } if(anshead!=anstail) for(int i=1 ; i<=cnt[a[anstail]] ; i++) printf("%d ",a[anstail]); for(int i=anstail-1 ; i>=anshead+1;i--) printf("%d ",a[i]); puts(""); }