首页 > 其他分享 >CF1916E Happy Life in University

CF1916E Happy Life in University

时间:2024-01-31 22:24:36浏览次数:33  
标签:Life int University 叶子 同色点 diff 300005 mx CF1916E

关于我赛时线段树忘了开四倍空间导致白吃了一发罚时这档逝

原题传送门

约定

\(x\) 子树内的叶子称为 \(x\) 的叶子。

与 \(x\) 颜色相同的点称为 \(x\) 的同色点或 \(x\) 色点。

所有在 \(x\) 子树内的、到 \(x\) 的路径上(两端不含)没有 \(x\) 的同色点的 \(x\) 的同色点称为 \(x\) 的极浅同色点。

分析

首先考虑两个点要是没有祖先关系,那必然是选择两个叶子最优。想到枚举 LCA 算贡献,则在每个点 \(x\) 得知道 \(x\) 的所有叶子到 \(x\) 的 diff 值。我们考虑在 dfs 回溯的时候维护这个东西。在我们回溯到一个点 \(x\) 的时候,\(x\) 的叶子到 \(x\) 对应的儿子的 diff 值已经有了。我们接下来要做的就是把 \(x\) 的所有 到 \(x\) 的路径上没有 \(x\) 的同色点的叶子 的 diff 值都加 \(1\)。为此,我们可以先把 \(x\) 的所有叶子的 diff 值都加 \(1\),然后枚举 \(x\) 的所有极浅同色点,把它们的叶子的 diff 值都减 \(1\)。于是问题转变成求 \(x\) 的所有极浅同色点。

我们反过来考虑。\(y\) 是 \(x\) 的其中一个极浅同色点,等价于从 \(y\) 往上跳,遇到的第一个 \(y\) 色点是 \(x\)。于是我们可以在 dfs 的时候维护一个栈,其中放着所有当前点 \(x\) 的祖先。然后我们就只需要在这个栈里找最后一个颜色与 \(x\) 相同的点 \(y\),那么 \(x\) 就一定是 \(y\) 的其中一个极浅同色点。对每种颜色开一个栈,这样就可以很方便地找到最后一个当前点的同色点。

求出每个点 \(x\) 到其所有叶子的 diff 值之后,我们枚举 \(x\) 的所有儿子 \(y\),对于每个 \(y\) 找到 \(x\) 到其叶子的 diff 的最大值,然后把这些最大值中的最大值和次大值相乘就是 \(x\) 作为 LCA 的最大贡献。

然后我们考虑两个点如果有祖先关系,那必然是一个是根,一个是叶子。直接找根到所有叶子的 diff 最大值即可。

最后还剩下把 \(x\) 的所有叶子的 diff 加 / 减 \(1\),求子树内叶子 diff 值 max。直接对叶子的 dfs 序开一个线段树,支持区间加区间 max 就没了。

至于为什么对每个点枚举所有它的极浅同色点不会 T,那是因为每个点至多是一个点的极浅同色点。所以每个点最多被枚举一次。

总复杂度是 \(O(n\log n)\)。

代码

#include <iostream>
#include <cassert>
#include <vector>
#define ll long long
using namespace std;
vector<int> vec[300005];
vector<int> sm[300005];
int clr[300005];
int f[300005];
int head[300005], nxt[300005], to[300005], ecnt;
void add(int u, int v) { to[++ecnt] = v, nxt[ecnt] = head[u], head[u] = ecnt; }
int L[300005], R[300005], ncnt;
ll ans = 1;
int lcnt = 0;
int n;
struct Segment_Tree {
    int mx[1200005], tg[1200005];
    inline void tag(int o, int t) { mx[o] += t, tg[o] += t; }
    inline void pushdown(int o) {
        if (!tg[o]) 
            return;
        tag(o << 1, tg[o]);
        tag(o << 1 | 1, tg[o]);
        tg[o] = 0;
    }
    inline void pushup(int o) { mx[o] = max(mx[o << 1], mx[o << 1 | 1]); }
    void Clear(int o, int l, int r) {
        mx[o] = tg[o] = 0;
        if (l == r) 
            return;
        int mid = (l + r) >> 1;
        Clear(o << 1, l, mid);
        Clear(o << 1 | 1, mid + 1, r);
    }
    void Add(int o, int l, int r, int L, int R, int v) {
        if (L <= l && r <= R) {
            tag(o, v);
            return;
        }
        pushdown(o);
        int mid = (l + r) >> 1;
        if (L <= mid) 
            Add(o << 1, l, mid, L, R, v);
        if (R > mid) 
            Add(o << 1 | 1, mid + 1, r, L, R, v);
        pushup(o);
    }
    int Query(int o, int l, int r, int L, int R) {
        if (L <= l && r <= R) 
            return mx[o];
        pushdown(o);
        int mid = (l + r) >> 1;
        if (R <= mid) 
            return Query(o << 1, l, mid, L, R);
        else if (L > mid) 
            return Query(o << 1 | 1, mid + 1, r, L, R);
        else 
            return max(Query(o << 1, l, mid, L, R), Query(o << 1 | 1, mid + 1, r, L, R));
    }
} seg;
void dfs(int x) {
    if (!vec[clr[x]].empty()) {
        int t = vec[clr[x]].size() * 1 - 1;
        sm[vec[clr[x]][t]].push_back(x);
    }
    if (!head[x]) {
        L[x] = R[x] = ++ncnt;
        seg.Add(1, 1, lcnt, ncnt, ncnt, 1);
        return;
    }
    vec[clr[x]].push_back(x);
    for (int i = head[x]; i; i = nxt[i]) {
        int v = to[i];
        dfs(v);
        R[x] = R[v];
        L[x] = (i == head[x] ? L[v] : L[x]);
    }
    vec[clr[x]].pop_back();
    seg.Add(1, 1, lcnt, L[x], R[x], 1);
    for (auto v : sm[x]) seg.Add(1, 1, lcnt, L[v], R[v], -1);
    int mx = 1, smx = 0;
    for (int i = head[x]; i; i = nxt[i]) {
        int v = to[i];
        int t = seg.Query(1, 1, lcnt, L[v], R[v]);
        if (t >= mx)
            smx = mx, mx = t;
        else if (t > smx) 
            smx = t;
    }
    ans = max(ans, 1ll * mx * smx);
}
signed main() {
    int tc;
    cin >> tc;
    while (tc--) {
        cin >> n;
        for (int i = 0; i <= n + 1; i++) {
            head[i] = 0;
            vec[i].clear();
            sm[i].clear();
            L[i] = R[i] = 0;
        }
        ans = 1;
        lcnt = ncnt = ecnt = 0;
         for (int i = 2; i <= n; i++) {
            cin >> f[i];
            add(f[i], i);
        }
        for (int i = 1; i <= n; i++) lcnt += (head[i] == 0);
        for (int i = 1; i <= n; i++) cin >> clr[i];
        dfs(1);
        cout << ans << "\n";
        seg.Clear(1, 1, lcnt);
    }
    return 0;
}

标签:Life,int,University,叶子,同色点,diff,300005,mx,CF1916E
From: https://www.cnblogs.com/forgotmyhandle/p/18000256

相关文章

  • academy和college "University"
    一文告诉你academy和college区别FFF看世界2024-01-2221:41上海哈利波特中的学院就是Academy"Academy"和"College"在一些语境中可能有交叉使用,但它们通常表示不同类型的教育机构。这里是它们的一般区别:Academy(学院):"Academy"一词通常指的是一所高中或中......
  • 初中英语优秀范文100篇-064WeChat,a New Way of Life-微信,一种新的生活方式
    PDF格式公众号回复关键字:SHCZFW064记忆树1Inmyopinion,usingWeChattochatisanewwayoflife.翻译在我看来,使用微信聊天是一种新的生活方式。简化记忆微信句子结构Inmyopinion介绍性短语,用于表达作者的观点主语:"usingWeChattochat"(使用微信聊天)......
  • 初中英语优秀范文100篇-063Persistence Makes My Life Better-坚持让我的生活更美好
    PDF格式公众号回复关键字:SHCZFW063记忆树1Persistenceislikeateacherofmine.翻译坚持就像我的一位老师简化记忆坚持句子结构主语:"Persistence"(坚持)谓语:"islike"(像是)补语:"ateacherofmine"(我的一位老师)2Itteachesmealotandmakesm......
  • 初中英语优秀范文100篇-053To Be a Qualifed Citizen-做一名合格市民
    PDF格式公众号回复关键字:SHCZFW053记忆树1Shanghaiistheplacewelivein.翻译上海是我们居住的地方简化记忆居住句子结构1主语(Shanghai):是一个名词短语,这个句子的主语是“上海”,一个中国的城市。2系动词(is):是一个动词,表示主语的性质、状态或特征。在这个句子中,is......
  • VMware vRealize Suite Lifecycle Manager 8.6 下载 - vRealize Suite 生命周期和内容
    使用vRealizeSuiteLifecycleManager管理vRealizeSuitevRealizeSuiteLifecycleManager针对vRealizeSuite产品提供完整的生命周期和内容管理功能。它通过自动执行部署、升级和配置来帮助客户缩短价值实现时间,同时将DevOps原则应用到vRealizeSuite内容管理中。vRea......
  • VMware vRealize Suite Lifecycle Manager 8.4 发布 - vRealize Suite 生命周期和内容
    使用vRealizeSuiteLifecycleManager管理vRealizeSuitevRealizeSuiteLifecycleManager针对vRealizeSuite产品提供完整的生命周期和内容管理功能。它通过自动执行部署、升级和配置来帮助客户缩短价值实现时间,同时将DevOps原则应用到vRealizeSuite内容管理中。vRea......
  • VMware Aria Suite Lifecycle 8.12 - 应用生命周期管理
    VMwareAriaSuiteLifecycle8.12-应用生命周期管理作者主页:sysin.org应用生命周期管理VMwareAriaSuiteLifecycle(以前称为vRealizeSuiteLifecycleManager)通过全面的应用生命周期和内容管理解决方案最大限度减少日常管理工作并提高终端用户的工作效率。全面的生命周期管理......
  • Gartner 魔力象限:全生命周期 API 管理 2023 (Magic Quadrant for Full Life Cycle API
    Gartner魔力象限:全生命周期API管理2023GartnerMagicQuadrantforFullLifeCycleAPIManagement2023作者主页:sysin.orgMagicQuadrantforAPIManagementPublished11October2023魔力象限API为数字化转型、现代化和数字化业务生态系统提供了基础,但管理和治理它们具有......
  • 浙江科技大学(Zhejiang University of Science and Technology)
    浙江科技大学(ZhejiangUniversityofScienceandTechnology)为浙江省属全日制本科高校,是一所具有硕士、学士学位授予权和外国留学生、港澳台学生招生权的特色鲜明的应用型省属本科高校,主校区位于杭州西湖区小和山高教园区,分校区位于安吉教科文新区,是教育部首批“卓越工程师教育培......
  • 信阳 信阳农林学院 Xinyang Agriculture and Forestry University 简 称信阳农林
    信阳农林学院外文名XinyangAgricultureandForestryUniversity简    称信阳农林·XinyangA&FUniversity(XYAFU) 历史沿革1910年(清宣统二年)学校在私立淮西中等学堂旧址(今汝南县城关)创建,校名为汝宁府中等实业学堂。1911年改称汝宁府官立甲种农业学校。1......