题解:CF2107E Ain and Apple Tree

首先考虑无解的情况。

当这棵树为一条链时,答案取到最大值。证明很简单,假设存在一个节点 uuu 至少有 222 个孩子节点,任取两个 v1,v2v_1,v_2v1,v2,则 dep(LCA⁡(v1,v2))=dep(u)\text{dep}(\operatorname{LCA}(v_1,v_2)) = \text{dep}(u)dep(LCA(v1,v2))=dep(u),此时进行调整,将 v1v_1v1v2v_2v2 改为直接相连,能够增大答案。即断开 (u,v2)(u,v_2)(u,v2),连接 (v1,v2)(v_1,v_2)(v1,v2),则有 dep(LCA⁡(v1,v2))=dep(v1)>dep(u)\text{dep}(\operatorname{LCA}(v_1,v_2)) = \text{dep}(v_1) > \text{dep}(u)dep(LCA(v1,v2))=dep(v1)>dep(u)。因此假设不成立,命题得证。

fif_ifi 表示 n=in = in=i 时的形成链的答案,则有:

fn=∑i=0n−1i×(n−i−1)=(n−1)∑i=0n−1i−∑i=0n−1i2=n(n−1)22−n(n−1)(2n−1)6=n(n−1)(n−2)6f_n = \sum _{i = 0}^{n - 1} i \times (n - i - 1) = (n - 1)\sum_{i = 0}^{n - 1}i - \sum_{i = 0}^{n - 1} i^2\\ =\frac{n(n - 1)^2}{2} - \frac{n(n - 1)(2n - 1)}{6} = \frac{n(n - 1)(n - 2)}{6} fn=i=0n1i×(ni1)=(n1)i=0n1ii=0n1i2=2n(n1)26n(n1)(2n1)=6n(n1)(n2)

因此 k>ans+1k > ans + 1k>ans+1 时无解。

首先构造出 iiii+1i + 1i+1 连边所形成的链,之后考虑进行调整。初始时 l=1,r=nl = 1,r = nl=1,r=n[l,r][l,r][l,r] 形成主链。每次考虑将 r−1r - 1r1rrr 断边并将 rrr 连至 lll 上。分析可知,对答案的减少量(fr−fr−1)−(fl+1−fl)−(l−1)(r−l−1)(f_r - f_{r - 1}) - (f_{l + 1} - f_l) - (l - 1) (r - l - 1)(frfr1)(fl+1fl)(l1)(rl1),化简可得 (r−1)(r−2)−l(l−1)2−(l−1)(r−l−1)\dfrac{(r - 1)(r - 2) - l(l - 1)}{2} - (l - 1)(r - l - 1)2(r1)(r2)l(l1)(l1)(rl1)。若可以操作,则完成后 r←r−1r \gets r - 1rr1,否则 l←l+1l \gets l + 1ll+1。重复调整操作直至符合条件。

接下去证明该调整操作的可行性。显然,在不断操作后,lllrrr 会不断趋近。当 r−l=2r - l = 2rl=2 时,消去 rrr 并代入得,该操作对答案的减少量为 (l+1)l−l(l−1)2−(l−1)(l+2−l−1)=1\frac{(l + 1)l - l(l - 1)}{2} - (l - 1)(l + 2 - l - 1) = 12(l+1)ll(l1)(l1)(l+2l1)=1,而 r−l=1r - l = 1rl=1 时不会改变答案。能够改变答案的减少量为 111,因此当有解时,总是存在一种调整方案。

代码如下:

#include <bits/stdc++.h>
#define init(x) memset (x,0,sizeof (x))
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define pii pair <int,int>
using namespace std;
const int MAX = 1e5 + 5;
const int MOD = 1e9 + 7;
inline ll read ();
int t,n;ll k;
int main ()
{
    t = read ();
    while (t--)
    {
        n = read ();k = read ();
        vector <vector <int>> ve (n + 1);
        ll res = 1ll * n * (n - 1) * (n - 2) / 6;
        if (res + 1 < k) {puts ("No");continue;}
        puts ("Yes");
        ll l = 1,r = n;res -= k;
        while (abs (res) > 1) 
        {
            ll del = (1ll * (r - 1) * (r - 2) - 1ll * l * (l - 1)) / 2 -  1ll * (r - l - 1) * (l - 1);
            if (del <= res) res -= del,ve[l].push_back (r--);
            else ++l;
        }
        for (int u = 1;u <= n;++u)
            for (auto v : ve[u]) printf ("%d %d\n",u,v);
        for (int i = 1;i < r;++i) printf ("%d %d\n",i,i + 1);
    }
    return 0;
}
inline ll read ()
{
    ll s = 0;int f = 1;
    char ch = getchar ();
    while ((ch < '0' || ch > '9') && ch != EOF)
    {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9')
    {
        s = s * 10 + ch - '0';
        ch = getchar ();
    }
    return s * f;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值