0%

[CF1091E]New Year and the Acquaintance Estimation题解

简单无向图的可视化,根据 Erdős–Gallai 定理将度数序列 \(d\) 排序可得,若满足

\[ \forall k\in[1,n],\sum_{i=1}^kd_k\le k\times(k-1)+\sum_{i=k+1}^n\min(k,d_i) \]

\[ \sum_{i=1}^nd_i\equiv0\ mod\ 2 \]

则序列可图,感性理解就是我们不断满足构成部分完全图的上界

稍加分析我们也可以发现,最后的答案是一个连续的序列简单证明就是若 \(d_n=i\)\(d_n=j\) 都是可图的,那么我们可以删去两边增加一条边的方法递推得到中间的合法值

所以这道题再套上一个二分即可

二分是二分一个区间的左右端点,因此我们需要分清什么时候偏大,什么时候偏小

\(i\) 时不满足条件,当 \(mid\ge d_i\) 时,\(mid\) 偏大,否则偏小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
using namespace std;
typedef long long int64;
inline int read(int f = 1, int x = 0, char ch = ' ')
{
while(!isdigit(ch = getchar())) if(ch == '-') f = -1;
while(isdigit(ch)) x = x*10+ch-'0', ch = getchar();
return f*x;
}
const int N = 5e5+5;
int n, p, ansl, ansr, b[N], tax[N], a[N], l, r; int64 s[N];
int valid(int mid)
{
for(int i = 0; i < n; ++i) tax[i] = 0; ++tax[mid];
for(int i = 1; i < n; ++i) ++tax[b[i]];
for(int i = n-1, j = 0; ~i; --i)
for(int k = 1; k <= tax[i]; ++k)
a[++j] = i;
for(int i = 1; i <= n; ++i) s[i] = s[i-1]+a[i];
for(int i = 1, j = n+1; i < n; ++i)
{
for(j = max(i+1, j); j > i+1&&a[j-1] <= i; --j);
if(s[i] > (j-1ll-i)*i+s[n]-s[j-1]+i*(i-1ll)) return a[i]<=mid?-1:1;
}
return 0;
}
int main()
{
n = read()+1; for(int i = 1; i < n; ++i) b[i] = read(), p ^= b[i]&1;
l = 0, r = (n-1-p)>>1, ansr = -1;
while(l <= r)
{
int mid = (l+r)>>1;
if(valid(mid<<1|p) == -1) r = mid-1;
else l = mid+1, ansr = mid;
}
l = 0, r = (n-1-p)>>1, ansl = -1;
while(l <= r)
{
int mid = (l+r)>>1;
if(valid(mid<<1|p) == 1) l = mid+1;
else r = mid-1, ansl = mid;
}
if(ansl > ansr||ansl == -1||ansr == -1) return puts("-1"), 0;
for(int i = ansl; i <= ansr; ++i) printf("%d ", i<<1|p); puts("");
return 0;
}