首页 > 其他分享 >「解题报告」CF768G The Winds of Winter

「解题报告」CF768G The Winds of Winter

时间:2023-06-03 19:44:13浏览次数:32  
标签:pre return Winter int mid CF768G rc Winds lc

真的不难,为啥是 3300*。还是模拟赛 T3,很气啊,为什么不先看这个题。

首先贪心很容易发现一定是将当前子树大小最大的那棵树的某个子树移动到最小的那个树内。那么我们记移动的这个子树的大小为 \(x\),所有树中最小的树大小为 \(a\),最大的为 \(c\),次大的为 \(b\),那么我们就是在最小化 \(\max\{a + x, b, c - x\}\)。这东西显然当 \(x = \frac{c - a}{2}\) 的时候取得最小值,但是 \(x\) 并不是什么都能取的,必须是这棵树中的某个子树的大小。那么我们数据结构维护一下某个子树内的所有树大小,那么我们就只需要找前驱后继即可。具体维护就直接用线段树合并即可。

然后就没东西了。具体维护可能有点细节,懒得写了。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int n;
vector<int> e[MAXN];
int siz[MAXN];
int rt;
void dfs1(int u, int pre) {
    siz[u] = 1;
    for (int v : e[u]) if (v != pre) {
        dfs1(v, u);
        siz[u] += siz[v];
    }
}
struct SegmentTree {
    struct Node {
        int cnt, lc, rc;
    } t[MAXN * 250];
    int tot;
    void pushUp(int p) {
        t[p].cnt = t[t[p].lc].cnt + t[t[p].rc].cnt;
    }
    void insert(int d, int &p, int l = 1, int r = n) {
        if (!p) p = ++tot, t[p].cnt = 1;
        else t[++tot] = t[p], p = tot, t[p].cnt++;
        if (l == r) return;
        int mid = (l + r) >> 1;
        if (d <= mid) insert(d, t[p].lc, l, mid);
        else insert(d, t[p].rc, mid + 1, r);
        pushUp(p);
    }
    int merge(int x, int y, int l = 1, int r = n) {
        if (!x || !y) return x + y;
        if (l == r) {
            int z = ++tot;
            t[z].cnt = t[x].cnt + t[y].cnt;
            return z;
        }
        int mid = (l + r) >> 1;
        int z = ++tot;
        t[z].lc = merge(t[x].lc, t[y].lc, l, mid);
        t[z].rc = merge(t[x].rc, t[y].rc, mid + 1, r);
        pushUp(z);
        return z;
    }
    int pre(int v, int p, int l, int r) {
        if (v < l) return 0;
        if (!t[p].cnt) return 0;
        if (r <= v) {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            return pre(v, t[p].rc, mid + 1, r) ?: pre(v, t[p].lc, l, mid);
        }
        int mid = (l + r) >> 1;
        if (v <= mid) return pre(v, t[p].lc, l, mid);
        return pre(v, t[p].rc, mid + 1, r) ?: pre(v, t[p].lc, l, mid);
    }
    int pre(int v, int p1, int p2, int p3, int l, int r) {
        if (v < l) return 0;
        if (!(t[p1].cnt - t[p2].cnt - t[p3].cnt)) return 0;
        if (r <= v) {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            return pre(v, t[p1].rc, t[p2].rc, t[p3].rc, mid + 1, r) ?: pre(v, t[p1].lc, t[p2].lc, t[p3].lc, l, mid);
        }
        int mid = (l + r) >> 1;
        if (v <= mid) return pre(v, t[p1].lc, t[p2].lc, t[p3].lc, l, mid);
        return pre(v, t[p1].rc, t[p2].rc, t[p3].rc, mid + 1, r) ?: pre(v, t[p1].lc, t[p2].lc, t[p3].lc, l, mid);
    }
    int suf(int v, int p, int l, int r) {
        if (v > r) return 0;
        if (!t[p].cnt) return 0;
        if (v <= l) {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            return suf(v, t[p].lc, l, mid) ?: suf(v, t[p].rc, mid + 1, r);
        }
        int mid = (l + r) >> 1;
        if (v > mid) return suf(v, t[p].rc, mid + 1, r);
        return suf(v, t[p].lc, l, mid) ?: suf(v, t[p].rc, mid + 1, r);
    }
    int suf(int v, int p1, int p2, int p3, int l, int r) {
        if (v > r) return 0;
        if (!(t[p1].cnt - t[p2].cnt - t[p3].cnt)) return 0;
        if (v <= l) {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            return suf(v, t[p1].lc, t[p2].lc, t[p3].lc, l, mid) ?: suf(v, t[p1].rc, t[p2].rc, t[p3].rc, mid + 1, r);
        }
        int mid = (l + r) >> 1;
        if (v > mid) return suf(v, t[p1].rc, t[p2].rc, t[p3].rc, mid + 1, r);
        return suf(v, t[p1].lc, t[p2].lc, t[p3].lc, l, mid) ?: suf(v, t[p1].rc, t[p2].rc, t[p3].rc, mid + 1, r);
    }
} st;
int root[MAXN];
void dfs2(int u, int pre) {
    st.insert(siz[u], root[u]);
    for (int v : e[u]) if (v != pre) {
        dfs2(v, u);
        root[u] = st.merge(root[u], root[v]);
    }
}
int ans[MAXN];
void dfs3(int u, int pre, int rt) {
    vector<pair<int, int>> x; 
    if (pre) x.push_back({ n - siz[u], 0 });
    for (int v : e[u]) if (v != pre) {
        x.push_back({ siz[v], v });
    }
    sort(x.begin(), x.end());
    if (x.size() == 1 || x.back().first == x[x.size() - 2].first) {
        ans[u] = x.back().first;
    } else {
        int a = x.front().first, b = x[x.size() - 2].first, c = x.back().first;
        int p = (c - a) / 2;
        ans[u] = c;
        if (x.back().second == 0) {
            int l = st.pre(p, root[::rt], root[u], rt, 1, n);
            int r = st.suf(p, root[::rt], root[u], rt, 1, n);
            int x = st.pre(p + siz[u], rt, 1, n);
            int y = st.suf(p + siz[u], rt, 1, n);
            if (l) ans[u] = min(ans[u], max({ a + l, b, c - l }));
            if (r) ans[u] = min(ans[u], max({ a + r, b, c - r }));
            if (x && x - siz[u] >= 0) ans[u] = min(ans[u], max({ a + (x - siz[u]), b, c - (x - siz[u]) }));
            if (y && y - siz[u] >= 0) ans[u] = min(ans[u], max({ a + (y - siz[u]), b, c - (y - siz[u]) }));
        } else {
            int l = st.pre(p, root[x.back().second], 1, n);
            int r = st.suf(p, root[x.back().second], 1, n);
            if (l) ans[u] = min(ans[u], max({ a + l, b, c - l }));
            if (r) ans[u] = min(ans[u], max({ a + r, b, c - r }));
        }
    }
    st.insert(siz[u], rt);
    for (int v : e[u]) if (v != pre) {
        dfs3(v, u, rt);
    }
}
int main() {
    scanf("%d", &n);
    if (n == 1) {
        printf("0\n");
        return 0;
    }
    for (int i = 1; i <= n; i++) {
        int u, v; scanf("%d%d", &u, &v);
        if (!u || !v) rt = u | v;
        else e[u].push_back(v), e[v].push_back(u);
    }
    dfs1(rt, 0), dfs2(rt, 0);
    dfs3(rt, 0, 0);
    for (int i = 1; i <= n; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

标签:pre,return,Winter,int,mid,CF768G,rc,Winds,lc
From: https://www.cnblogs.com/apjifengc/p/17454449.html

相关文章

  • 外汇天眼:Winter平台积极鼓吹借贷投资黄金,诱导入金建仓诈骗30万!
    对现代人来说,通过社交平台认识新朋友已经是很普遍的事情。然而,网络交友确实也有一定程度的风险,近年来有愈来愈人落入诈骗集团假冒帅哥美女的杀猪盘陷阱,并因此蒙受莫大的损失,日前外汇天眼就收到一位投资人的爆料,控诉黑平台Winter的恶行。根据受害者的回忆,她是在社群网站IG上被一位......
  • Walkthrough-WINTERMUTE 1
    0x01环境靶机地址:https://www.vulnhub.com/entry/wintermute-1,239/两个靶机,做网络隔离STRAYLIGHT一张网卡桥接,另一张仅主机模式,桥接网卡时,可能有点问题,重选一下网卡就好了Kali做桥接网卡NEUROMANCER仅主机kali和NEUROMANCER网络不联通0x02过程STRAYLIGHT1.信息收......
  • 【数字敏捷性】上海道宁与​SolarWinds为您提供全面的可观察性、IT 服务管理和数据库
     SolarWindsPlatform是业界先进的统一监控可观察性和服务管理平台它是新一代SolarWinds可观察性解决方案的基础并提供了我们如何为客户解决可观察性挑战的架构网络管理工具从配置和流量智能到性能监控和拓扑映射可以轻松查看、理解和解决问题一种集成的多供应商......
  • Holt-Winters模型原理分析及代码实现(python)
    引言最近实验室老师让我去预测景区内代步车辆的投放量,于是乎,本着“一心一意地输出年富力强的劳动力”这份初心,我就屁颠屁颠地去找资料,然后发现了Holt-Winters模型,感......
  • SMU Winter 2023 Round #13
    B.BM算日期题意:就是给定两个整数n,k,n是第一个日期,n+k是第二个日期,如果n+k>9999,那么9999-(n+k-9999)是第二个日期,算这两个日期中有多少个闰年。思路:首先根据题目规则得到......
  • SMU Winter 2023 Round #14
    A.解开束缚缠丝Ⅱ题意:给出n个字母(含大小写),求它们能构成最长回文串的长度。思路:找到里面成对的字符串有多少,然后如果有多出来的就+1,如果没有了就不加了,如果有三个只能算......
  • SMU Winter 2023 Round #12 (Div.2)
    A.KK画猪题目:输入pig,输出一些字符。代码:点击查看代码importjava.util.Scanner;publicclassMain{ publicstaticvoidmain(String[]args){ Scannerscanne......
  • SMU Winter 2023 Round #11 (Div.2)
    A.BCD题意:输入两个数,一个是数的数量N,另一个是每个箱子能够装多少书M,问需要多少个箱子。思路:我们只需要用书n的数量去除以容量m,然后判断一下取模有没有余数,有的话就结果......
  • SMU Winter 2023 Round #10 (Div.2)
    A.社团招新题目:计网院里面有n个学生。他们中任意一些人都可以成立一个社团。如果社团满足3男有1女,就可以一对情侣一对基。但是院里要求这些社团有如下要求:•为方便......
  • SMU Winter 2023 Round #9 (Div.2)
    A.WhoisThe19thZUCCPCChampion签到题,输出即可。B.JiubeiandOverwatch题目:JiubeilovesplayingOverwatchevenifitisalongtimesincethelastupdate.......