首页 > 其他分享 >CF1610H Squid Game

CF1610H Squid Game

时间:2023-12-12 18:46:12浏览次数:26  
标签:fir cnt int Squid son CF1610H fa Game nex

题意

给定一棵树,以及 \(m\) 条路径。

让你选出最少的点,使得对于每一条路径,都有一个点距离链上的点离端点更近。

Sol

考虑将每一条路径分为直链和曲链考虑。

注意到所有的曲链最多对答案有 \(1\) 的贡献。

考虑直链的情况。

注意到一个很显然的东西。

对于一个选择的点,如果她的上方不是端点,那她就可以一直向上移动,答案不会变劣。

考虑对于直链做树形dp。

设 \(f_i\) 表示在 \(i\) 子树内满足所有直链的贡献的最小答案。

对于平凡的情况,\(f_u = \sum f_v\)。

如果当前节点的父亲是一个端点,考虑这样一种情况:

如果当前有儿子有 \(dp\) 值,那么除了当前儿子以外,都不需要有贡献。

所以 \(f_u = max(f_v + 1, f_u)\)。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <vector>
using namespace std;
#ifdef ONLINE_JUDGE

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

#endif
int read() {
    int p = 0, flg = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') flg = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        p = p * 10 + c - '0';
        c = getchar();
    }
    return p * flg;
}
void write(int x) {
    if (x < 0) {
        x = -x;
        putchar('-');
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}
const int N = 3e5 + 5, M = 6e5 + 5;

namespace G {

array <int, N> fir;
array <int, M> nex, to;
int cnt;
void add(int x, int y) {
    cnt++;
    nex[cnt] = fir[x];
    to[cnt] = y;
    fir[x] = cnt;
}

}

namespace Hpt {

using G::fir; using G::nex; using G::to;
array <int, N> fa, dep, son, siz;

void dfs1(int x) {
    siz[x] = 1;
    for (int i = fir[x]; i; i = nex[i]) {
        if (to[i] == fa[x]) continue;
        fa[to[i]] = x;
        dep[to[i]] = dep[x] + 1;
        dfs1(to[i]);
        siz[x] += siz[to[i]];
        if (siz[to[i]] > siz[son[x]]) son[x] = to[i];
    }
}

array <int, N> dfn, idx, top;
int cnt;

void dfs2(int x, int Mgn) {
    cnt++;
    dfn[x] = cnt;
    idx[cnt] = x;
    top[x] = Mgn;
    if (son[x]) dfs2(son[x], Mgn);
    for (int i = fir[x]; i; i = nex[i]) {
        if (to[i] == fa[x] || to[i] == son[x]) continue;
        dfs2(to[i], to[i]);
    }
}

int lca(int x, int y) {
    while (top[fa[y]] != top[x] && y)
        y = top[fa[y]];
    if (dep[son[x]] < dep[y]) return son[x];
    else return y;
}

}

array <vector <int>, N> isl;
array <int, N> f;

void dfs(int x) {
    for (int i = G::fir[x]; i; i = G::nex[i]) {
        if (G::to[i] == Hpt::fa[x]) continue;
        dfs(G::to[i]), f[x] += f[G::to[i]];
    }
    if (isl[x].size()) f[x] = max(f[x], f[isl[x][0]] + 1);
}

vector <int> __;
int _;

int read_() { return __[_++]; }

int main() {
    int n = read(), m = read();
    for (int i = 2; i <= n; i++) {
        int x = read();
        G::add(i, x), G::add(x, i);
    }
    Hpt::dfs1(1), Hpt::dfs2(1, 0);
    for (int i = 1; i <= m; i++) {
        int x = read(), y = read();
        if (Hpt::dep[x] > Hpt::dep[y]) swap(x, y);
        int z = Hpt::lca(x, y);
        // write(z), puts("");
        if (Hpt::fa[y] == x) return puts("-1"), 0;
        if (Hpt::fa[z] != x) __.push_back(x), __.push_back(y);
        else isl[z].push_back(y);
    }
    dfs(1); int ans = f[1];
    for (int i = 1; i <= __.size() / 2; i++) {
        int x = read_(), y = read_();
        ans = max(ans, f[x] + f[y] + 1);
    }
    write(ans), puts("");
    return 0;
}

标签:fir,cnt,int,Squid,son,CF1610H,fa,Game,nex
From: https://www.cnblogs.com/cxqghzj/p/17897572.html

相关文章

  • 奇偶game
    证明一下边带权做法的充分性我们考虑异或和对一个01序列,我们做一个异或前缀和,设为\(sum_n\),那么\(a_i=sum_i\enspacexor\enspacesum_{i-1}\)对任何时刻的没有产生矛盾的并查集森林,我们随便给每个森林的根节点赋值一个0或1,那么其他所有节点的值也能够推导出来(注意中途不可能重......
  • Game = Rust + WebAssembly + 浏览器
    ❝努力成为一个情绪价值的提供者❞大家好,我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder。前言在上一篇Rust编译为WebAssembly在前端项目中使用我们通过一个简单的HelloWorld的Demo,讲述了如何将Rust编译为WebAssembly,并在前端项目中使用。虽然,......
  • games101-2 透视深度插值矫正与抗锯齿分析
    透视深度插值矫正与抗锯齿分析深度插值的差错原因透视深度插值公式推导games101中的错误msaa与ssaa简要定义games101中ssaa的实现games101中msaa的实现深度插值的差错原因当投影的图形与投影的平面不平行时,这时进行透视投影,从上图中可以看出,投影平面上的线段时均匀......
  • ICPC2022Hangzhou C No Bug No Game 题解
    LinkICPC2022HangzhouCNoBugNoGameQuestion给定\(n\)个物品和上限\(k\),要求最大化分数,物品的选择顺序可以任意第\(i\)个物品一行\(p_i\)代表个数,后面\(p_i\)个\(w_j\)代表容量,定义\(sum=\sum\limits_{j=1}^{i-1}\),对于第\(i\)个物品\(sum+p_i\lek\)......
  • A. Flipping Game
    A.FlippingGame本质上是让我们找出一段区间内\(0\)的个数大于\(1\)的个数的最多的区间,且必须进行一次操作,所以可以考虑区间\(dp\),或者最小子序列和1最小子序列和\[\begin{aligned}dp_i是以a_i结尾的最小子序列和\\dp_i=\min(dp_{i-1}+a[i],a[i])\end{aligned}\]#inc......
  • Codeforces Round 912 (Div. 2) E - Geo Game
    考虑什么时候会改变答案的奇偶,显然可以根据\(x\oplusy\)的奇偶性分组,在组内进行跳跃不会改变,只有当组间跳跃的时候才会改变。打表观察先手什么时候必胜,其中:\(u\)是当前获胜目标为奇/偶(1/0),\(v\)是位于哪一组,\(a,b\)代表两组还剩多少,\(st\)代表当前答案的奇偶性。intdfs(intu,......
  • Game Physics
    BasicconceptsformphysicsRigidBodyClassificationSingleparticlesandparticlessystemareexamplesofdiscretematerial.Thestandardnotationis\[Q_{total}=\sum\limits_{i=1}^{p}Q_{i}\]Anothertypeofbodyisreferredtoasacontinuousma......
  • [Codeforces] CF1747C Swap Game
    游戏(game.cpp)—CF1747C—1200\(时间:1s\space|\space空间:250MB\)题面翻译Alice和Bob两个人在玩游戏。有一个长度为\(n\)的序列\(a\),Alice和Bob两人轮流完成一个操作,Alice先开始。每个人可以将数列的第一个数减\(1\),并将它与后面序列的一个数进行交换,如果一个......
  • 0xGame week4-WEB wp
    0xGame个人结语完结撒花!!!学到了很多很多,算是我这个WEB菜鸡过渡期的一个见证吧。0xGame虽然也没做出来几道(大嘘),但是一步步跟着复现也学了很多好玩的知识点和思路,希望下次能进化成WEBak哥hhhhhh~~~~来看最后一周,全是java框架,麻了。spring整体不难,hint把解题方法基本写脸上了,网上......
  • pygame播放视频并实现音视频同步
    一、前言在我接触pygame时最新的pygame已经不支持movie模块,这就导致在pygame播放视频变成一个问题,网上搜了下解决方案有两个:一是使用opencv播放视频,再结合pygame.mixer来播放音频二是使用moviepy播放视频,再结合pygame.mixer播放音频上述两个方案其实都是先将mp4的视频分离成“......