HOJ1127听风

HOJ1127听风

该网页无法正常运作

题面(题面难懂这就是语文题

一棵根节点为1的树,所有边权均为1,每个节点有不同的颜色C。对这棵树进行游览并统计贡献。

游览方式
1.如果一个节点被游览过就不再游览。
2.如果在i号节点,它是叶子节点或者所有儿子都被游览过则停在该节点。
3.如果第 i号节点存在儿子没有游览过,则挑选所有未游览的儿子中val[x]最小的一个继续行走。val[x] = min{y|y${\in}$x的子树}。
可以任意选择在游览几个节点后结束游览

每游览一个节点,贡献会加上 这个节点到根节点以及它的子树中颜色的种类 $-$ 这个节点到根节点的路径长度

游览结束后,会给很多路径

贡献会加上max(每条路径上被游览的点数 $-1$,$0$)$*$题目提供的权值z
最终答案为游览结束后的所有可能贡献中的最大值

这题该咋做

首先dfs求出游览的顺序,然后树上差分,把最后路径的权值扔到节点上,最后按照游览顺序遍历这颗树,统计当前的总贡献,与答案取max。
至于节点的颜色,因为数据比较小bitset状态压缩就可以过。std给的是dsu on tree,等我学会了再来更新。

涉及的知识点

LCA

LCA
这题我用倍增毕竟Tarjan不会

树上差分

其实是第一次写树上差分
这道题在处理路径的时候使用树上差分。但是给的是路径上节点数-1,该怎么处理呢?
由于游览顺序已知,我们只要不记录这条路径上最先被游览的节点,就可以保证在计算这条路径时有-1的效果。
树上差分的标记是打在左右两个节点的,我们只要挑选出这两个中先被游览的点,把标记打在他的父亲即可。

dsu on tree

不会·咕咕咕一个好题

代码

这个是bitset的代码,极慢,卡着空间。。。

#include <iostream>
#include <cstdio>
#include <bitset>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <ctime>
namespace fdata
{
inline char nextchar()
{
    static const int BS = 1 << 21;
    static char buf[BS], *st, *ed;
    if (st == ed)
        ed = buf + fread(st = buf, 1, BS, stdin);
    return st == ed ? -1 : *st++;
}
template <typename T>
inline T poread()
{
    T ret = 0;
    char ch;
    while (!isdigit(ch = nextchar()))
        ;

    do
        ret = ret * 10 + ch - '0';
    while (isdigit(ch = nextchar()));
    return ret;
}
} // namespace fdata
using fdata::poread;
using namespace std;
const int INF = 1 << 29;
const int MAXN = 1e5 + 5;
const int MAXC = 4e3 + 7;
int n, m, c, t;
int head[MAXN], ver[MAXN << 1], nxt[MAXN << 1], tot; //邻接表
inline void add(const int &x, const int &y)
{
    ver[++tot] = y;
    nxt[tot] = head[x];
    head[x] = tot;
}
struct node //记录节点信息
{
    bitset<MAXC> lian, c;
    vector<int> vct;
    int deep;
    int son;
    int siz;
} pt[MAXN];
int dfn[MAXN], cnt;
int f[MAXN][19]; // lca
bool cmp(const int &x, const int &y)
{
    return pt[x].son < pt[y].son;
}
void dfs1(int x) //处理子树集合,父亲节点
{
    pt[x].son = x;
    pt[x].lian |= pt[f[x][0]].lian;
    for (register int i = head[x], y = ver[i]; i; i = nxt[i], y = ver[i])
    {
        if (y == f[x][0])
            continue;
        dfs1(y);
        pt[x].c |= pt[y].c;
        pt[x].son = min(pt[x].son, pt[y].son);
    }
}
void dfs2(int x)
{
    for (register int i = head[x]; i; i = nxt[i])
        if (ver[i] != f[x][0])
            pt[x].vct.push_back(ver[i]);
    sort(pt[x].vct.begin(), pt[x].vct.end(), cmp);
    for (register vector<int>::iterator it = pt[x].vct.begin(); it != pt[x].vct.end(); ++it)
        dfs2(*it);
    dfn[x] = ++cnt;
    pt[x].vct.clear();
}
int lca(int x, int y)
{
    if (pt[x].deep > pt[y].deep)
        swap(x, y);
    int t = (int)(log(n) / log(2)) + 1;
    for (register int i = t; i >= 0; --i)
    {
        if (pt[f[y][i]].deep >= pt[x].deep)
            y = f[y][i];
    }
    if (y == x)
        return x;
    for (register int i = t; i >= 0; --i)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    return f[x][0];
}
long long Ans = 0;
long long ans = 0;
void dfs3(int x)
{
    for (register int i = head[x]; i; i = nxt[i])
    {
        int y = ver[i];
        if (y == f[x][0])
            continue;
        dfs3(y);
        pt[x].siz += pt[y].siz;
    }
}
void dfs4(int x)
{
    for (register int i = head[x]; i; i = nxt[i])
        if (ver[i] != f[x][0])
            pt[x].vct.push_back(ver[i]);
    sort(pt[x].vct.begin(), pt[x].vct.end(), cmp);
    for (register vector<int>::iterator it = pt[x].vct.begin(); it != pt[x].vct.end(); ++it)
        dfs4(*it);
    ans = (long long)ans + (1ll * pt[x].lian.count() - pt[x].deep + 1) + (1ll * pt[x].siz);
    Ans = max(ans, Ans);
    pt[x].vct.clear();
}
inline void bfs()
{
    queue<int> q;
    q.push(1);
    pt[1].deep = 1;
    f[1][0] = -1;
    while (q.size())
    {
        int x = q.front();
        q.pop();
        for (register int i = head[x], y = ver[i]; i; i = nxt[i], y = ver[i])
        {
            if (pt[y].deep)
                continue;
            pt[y].deep = pt[x].deep + 1;
            f[y][0] = x;
            for (register int j = 1; j <= t; ++j)
            {
                f[y][j] = f[f[y][j - 1]][j - 1];
            }
            q.push(y);
        }
    }
    while (q.size())
        q.pop();
}
bitset<MAXC> iii;
signed main()
{
#ifdef lky233
    freopen("testdata.in", "r", stdin);
    freopen("testdata.out", "w", stdout);
#endif
    n = poread<int>(), m = poread<int>(), c = poread<int>();
    t = log(n) / log(2) + 1;
    for (register int i = 1; i <= n; ++i)
        pt[i].lian[poread<int>()] = true, pt[i].c = pt[i].lian;
    for (register int i = 1, x, y; i < n; ++i)
    {
        x = poread<int>(), y = poread<int>();
        add(x, y), add(y, x);
    }
    bfs();
    dfs1(1);
    for (register int i = 1; i <= n; ++i)
        pt[i].lian = pt[i].c | pt[i].lian;
    // for (register int i = 1; i <= n; ++i)
    //     cerr << pt[i].lian.count() << " ";
    // cerr << endl;
    dfs2(1);
    for (register int i = 1, x, y, z; i <= m; ++i)
    {
        x = poread<int>(), y = poread<int>(), z = poread<int>();
        if (x == y)
            continue;
        if (dfn[x] >= dfn[y])
            swap(x, y);
        x = f[x][0];
        if (x)
            pt[x].siz += z;
        if (y)
            pt[y].siz += z;
        int L = lca(x, y);
        if (L)
            pt[L].siz -= z;
        if (f[L][0])
            pt[f[L][0]].siz -= z;
        // cerr << x << y << L << f[L][0] << endl;
    }
    dfs3(1);
    dfs4(1);
    cerr << "ans: ";
    cerr << Ans << endl;
    cout << Ans << endl;
    cerr << clock() << "ms" << endl;
    return 0;
}

至于 dsu on tree 回头更新

坑点

在树上差分标记的时候,给了一个1-1的路径,这个时候父亲跳到了上面,0有了+3-3-3的标记,1有了+3的标记,查询时导致少了-3,挂掉了。

持续更新ing

感谢nofind大佬解释题面,教我树上差分
ありがとうございました。

原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11541759.html

时间: 2024-08-01 17:58:29

HOJ1127听风的相关文章

[更新]用最先进的理念打造最特别的串口调试工具--听风(原Wise#Pragma)

软件主要界面 "听风"是一款独特的串口调试工具,主要有以下功能及特点: 1.能自动列举本机存在的串口,能显示串口详细描述及串口号,省去打开设备管理器查看串口的麻烦 2.能自动识别新增的串口及移除的串口 3.能很好的支持中文接收与发送 4.分离十六进制发送与文本发送窗口,省去切换麻烦 5.独创的右键菜单串口设定,及多种方便快捷选择串口的方式:如快捷键,鼠标滚轮 6.独创的右键菜单保存常用数据功能,让调试单片机更方便 7.独创的一次发送功能,不再为发送一次数据,要先打开串口的然后再关闭的麻

且听风吟——三小张

缺炼 “缺炼!”这不是我说的,这是兵哥说我的. 搬上来之前,我们8个人做过一次反省,张翀挨着我,快到我反省时,我问张翀,你看我这耳朵红呗?张翀说,红,你热昂?我说,没事,没事.张翀就拉上了窗帘. 到我反省了,我说,刚才我问张翀,你看我耳朵红不,张翀说红,并且很体贴的拉上了窗帘.其实我是内热,为什么?两点,一是心跳加速,血热:二是骨骼肌颤栗,产热. 到我说的时候我就很紧张,好像又不单纯是虚荣心作怪,这就有了兵哥说的“缺炼”. 确实是缺炼. 创造更大的价值 好,书接前文,上次说到卖豆角这个业务分三层

听风讲MVC丶 —— 一言不合就撸码 (未完待续&#183;&#183;&#183;&#183;&#183;&#183;)

     希望你看了此小随 可以实现自己的MVC框架     也祝所有的程序员身体健康一切安好                                                                                                                                                ——久伴深海丶默 1.什么是前端控制器(font controller).Java Web中的前端控制器是应用的门面,

青春三部曲(《且听风吟》,《一九七三年的弹子球》,《寻羊冒险记》)--[日]村上春树

原本想把这三本书分开来着,但是细想了一下,还是和在一起好一些 村上春树的青春三部曲,<且听风吟>,<一九七三年的弹子球>,<寻羊冒险记> 我是先看了<寻羊冒险记>,然后再去读<且听风吟>,<一九七三你的弹子球> 进来看了不少关于村上春树的作品,怎么说好呢?那种风格和文体我想是吸引了我! 三本书,实在不错! 下面是我的书摘: <寻羊冒险记> * 失业使我心情畅快起来.我正一点点简化.我失去了故乡,失去了青春,失去了朋友,失去

没关系,且听风吟。

我有些紧张. 不知不觉,大学生活就快结束了.可能也不算不知不觉. 有时候,我仿佛切身体会到,它从我身边跑过,只不过是它没回头跟我道别. 我好像想留住些什么... 以前的梦想是成为一名作家,优秀的作家. 无数次幻想着未来的某个早晨,我独自从一个满园春意的小院子醒来(虽然我不喜欢春天,不喜欢绿色,但是如果要成为一名作家,我想,什么东西都得尝试去喜欢吧),我坐在一张摇椅上,想到什么便记下什么.周围的人说着三十岁的我,活得像一个七十岁的老头.”不过,那并没关系“,我这样低喃道... 或者,在某个寒冷的夜

连载《一个程序猿的生命周期》-《发展篇》- 26.且听风吟,静待花开,慢慢走向人生赢家

昨天一早感觉天气很好,完全没有上班的意愿.上午赶到公司处理一些无关紧要的事儿,于是乎下午带着大宝去八大处爬山,在感受自然风光的同时想到一句话:且听风吟,静待花开.在人生过程中所做出的努力,也需要静静等待开花结果,不过等待是一件很痛苦的事. 从去年9月份开始很少在公司,基本上一直处于出差状态,一般是周五晚上回京.周日晚上出差,关键时期周末搭进去了.正值项目推进困难.攻坚克难的时候,老婆怀二宝已经有27周了.如果说用户和公司层面都认为你是项目具体负责执行的最佳人选,请问还有其他的选择余地吗?已经执行

且听风吟

Listen  wind 今晚独自走在校园的油泊路上,想独自静静,虽然是快到夏天了,但天津的晚风还是有一点凉意不管它了,插上耳机,独自漫无目的的在这路上走着,随手看到木凳就坐了下来,不知不觉的仰望起头.发现天上仅仅挂着一轮残缺不全的月亮,周围一点星星都没有,但幸好月亮很亮.风一阵一阵的吹到脸上,摘下耳机,听着风的声音,看着风吹来的方向 . 脑子里不知从何时开始,变的有点碎碎念,时时有些感怀和念想,时时又有些幻想和希望,再过三个月,这心中纷繁复杂的"一年"就要过去了.周围发生的一切犹如这

且听风吟,时光真疯狂

突然落下的夜晚 灯火已隔世般阑珊 昨天已经去得很远 我的窗前已模糊一片 大风声 像没发生 太多的记忆 又怎样放开我的手 怕你说 那些被风吹起的日子 在深夜收紧我的心 日子快消失了一半 那些梦又怎能做完 你还在拼命的追赶 这条路究竟是要去哪儿 大风声 像没发生 太多的记忆 又怎样放开我的手 怕你说 那些被风吹起的日子 在深夜收紧我的心 哎呀 时光真疯狂 我一路执迷与匆忙 依稀悲伤 来不及遗忘 只有待风将她埋葬 咿呀 咿呀 待风将她埋葬 咿呀 咿呀 待风将她埋葬 咿呀 咿呀 我们曾在路上 咿呀 咿呀

极客时间-左耳听风-程序员攻略-软件设计

程序员练级攻略:软件设计 编程范式 学习编程范式可以让你明白编程的本质和各种语言的编程方式.因此,我推荐以下一些资料,以帮助你系统化地学习和理解. 极客时间的<编程范式游记>系列文章,目录如下. 编程范式游记(1)- 起源 编程范式游记(2)- 泛型编程 编程范式游记(3)- 类型系统和泛型的本质 编程范式游记(4)- 函数式编程 编程范式游记(5)- 修饰器模式 编程范式游记(6)- 面向对象编程 编程范式游记(7)- 基于原型的编程范式 编程范式游记(8)- Go 语言的委托模式 编程范式