这道题可以用线段树合并做,网上的题解基本上都是线段树合并的。

但是为什么我就偏偏要用dsu on tree......

题目传送门

dsu on tree的方法类似[CF1009F] Dominant Indices(这是我之前写的题解)。

但是这道题要把树链操作变成某点到根的操作,最后统计子树贡献和。

子树贡献有正有负,不能像那道题那样用堆维护最大值(在这卡了半天)。

因为那道题只有加,这道题有加有减。

可能加上之后又减掉了,但是堆给出的最大值会是减掉之前的值(因为值更大)。

所以用线段树维护一下最大值。

这个线段树是比较简单的,支持单点修改即可。

查询时必然查询的是0~n的全局最大值。

所以就是线段树根的最大值喽。

注意线段树必须有一个0的位置。

因为如果没有救济粮的话要输出0。

至于如果有多种救济粮存放次数一样,怎么输出编号最小的。

在线段树向上更新的时候:(具体见代码第82行)

要这么写:if(mv[num<<1]>=mv[num<<1|1])

不能这么写:if(mv[num<<1]>mv[num<<1|1])

这样可以保证如果两边的最大值一样,会用左边的(也就是编号较小的)来更新。

怕卡,lca用的树剖。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; int n,m;
int hd[],nx[],to[],ec;
int fir[],bes[],kd[],fl[],qc;
int f[],son[],sz[],d[],tp[]; void edge(int af,int at)
{
to[++ec]=at;
nx[ec]=hd[af];
hd[af]=ec;
} void mark(int p,int pkd,int pfl)
{
kd[++qc]=pkd;
fl[qc]=pfl;
bes[qc]=fir[p];
fir[p]=qc;
} void pre(int p,int fa)
{
f[p]=fa;
d[p]=d[fa]+;
sz[p]=;
for(int i=hd[p];i;i=nx[i])
{
if(to[i]==fa)continue;
pre(to[i],p);
sz[p]+=sz[to[i]];
if(sz[to[i]]>sz[son[p]])son[p]=to[i];
}
} void findtp(int p)
{
if(p==son[f[p]])tp[p]=tp[f[p]];
else tp[p]=p;
for(int i=hd[p];i;i=nx[i])
if(to[i]!=f[p])findtp(to[i]);
} int lca(int x,int y)
{
while(tp[x]!=tp[y])
d[tp[x]]>d[tp[y]]?x=f[tp[x]]:y=f[tp[y]];
return d[x]<d[y]?x:y;
} int ans[];
int lb[],rb[],mc[],mv[]; void build(int num,int l,int r)
{
lb[num]=l,rb[num]=r;
if(l==r)
{
mc[num]=l;
return;
}
int mid=(l+r)>>;
build(num<<,l,mid);
build(num<<|,mid+,r);
} void update(int num,int p,int v)
{
if(lb[num]==rb[num])
{
mv[num]+=v;
return;
}
int mid=(lb[num]+rb[num])>>;
if(p<=mid)update(num<<,p,v);
else update(num<<|,p,v);
if(mv[num<<]>=mv[num<<|])
mv[num]=mv[num<<],mc[num]=mc[num<<];
else
mv[num]=mv[num<<|],mc[num]=mc[num<<|];
} void add(int p)
{
for(int i=hd[p];i;i=nx[i])
if(to[i]!=f[p])add(to[i]);
for(int i=fir[p];i;i=bes[i])
update(,kd[i],fl[i]);
} void del(int p)
{
for(int i=hd[p];i;i=nx[i])
if(to[i]!=f[p])del(to[i]);
for(int i=fir[p];i;i=bes[i])
update(,kd[i],-fl[i]);
} void dsu(int p,int keep)
{
for(int i=hd[p];i;i=nx[i])
if(to[i]!=f[p]&&to[i]!=son[p])
dsu(to[i],);
if(son[p])dsu(son[p],);
for(int i=hd[p];i;i=nx[i])
if(to[i]!=f[p]&&to[i]!=son[p])
add(to[i]);
for(int i=fir[p];i;i=bes[i])
update(,kd[i],fl[i]);
ans[p]=mc[];
if(!keep)del(p);
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
edge(a,b);
edge(b,a);
}
pre(,);
findtp();
build(,,);
for(int i=;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int l=lca(x,y);
mark(x,z,);
mark(y,z,);
mark(l,z,-);
if(l!=)mark(f[l],z,-);
}
dsu(,);
for(int i=;i<=n;i++)printf("%d\n",ans[i]);
return ;
}

洛谷P4556 雨天的尾巴

[洛谷P4556] 雨天的尾巴的更多相关文章

  1. 洛谷P4556 雨天的尾巴(线段树合并)

    洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...

  2. 洛谷P4556 雨天的尾巴 线段树

    正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...

  3. [洛谷 P4556] 雨天的尾巴

    传送门 Solution 线段树合并的入门题 lca可以在dfs的时候离线求(用并查集) 更新的点有每条链的两个端点,它们的lca和dad[lca] 为了节省空间,lca和dad[lca]的更新可以先 ...

  4. 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告

    P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...

  5. 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)

    题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...

  6. 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)

    传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...

  7. 【洛谷P4556】 雨天的尾巴

    题面 题解 线段树合并 我们看到这道题目首先可以想到树上差分,然后\(dfs\)合并 发现题目让我们求的东西很好用线段树维护 于是可以想到线段树合并 全世界只有我写指针版动态开点线段树(大雾 如果你要 ...

  8. [洛谷P4556][BZOJ3307]雨天的尾巴-T3订正

    线段树合并+树上差分 题目链接(···) 「简单」「一般」——其实「一般」也只多一个离散化 考试时想法看>这里< 总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每 ...

  9. P4556 雨天的尾巴 线段树合并

    使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u, ...

随机推荐

  1. openvino资源

    Intel OpenVINO介紹及樹莓派.Linux的安裝 https://chtseng.wordpress.com/2019/01/21/intel-openvino%E4%BB%8B%E7%B4 ...

  2. Django框架(一):MVC设计模式、Django简介

    1. MVC设计模式 MVC设计模式:Model-View-Controller简写. 最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪8 ...

  3. shell手册

    摘自雪松同学 0说明{ # shell实例手册最新下载地址: http://hi.baidu.com/quanzhou722/item/f4a4f3c9eb37f02d46d5c0d9 # pytho ...

  4. 使script.bin文件配置生效的驱动

    1.问题:在全志方案中如果需要设置上拉或者下拉模式,需要在script.bin(先转换为script.fex)中配置gpio口  如: 但是配置好后是不会生效的,需要写一个驱动来通过读取这个文件的gp ...

  5. 使用idea创建spring mvc项目图文教程

    使用idea创建spring mvc项目图文教程 前言: 使用惯了eclipse的朋友,如果刚换成了idea或许有些不习惯.但是使用idea之后,就会love上idea了.本文将通过图文讲解怎么通过i ...

  6. Prefix and Suffix

    题目描述 Snuke is interested in strings that satisfy the following conditions: The length of the string ...

  7. mac下停止和启动mysql命令

    启动MySQL服务 sudo /usr/local/MYSQL/support-files/mysql.server start   停止MySQL服务 sudo /usr/local/mysql/s ...

  8. [LC] 234. Palindrome Linked List

    Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false ...

  9. 3dmax2019卸载/安装失败/如何彻底卸载清除干净3dmax2019注册表和文件的方法

    3dmax2019提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装3dmax2019失败提示3dmax2019安装未完成,某些产品无法安装,也有时候想重新安装3 ...

  10. 深入探讨Java中的异常与错误处理

    Java中的异常处理机制已经比较成熟,我们的Java程序到处充满了异常的可能,如果对这些异常不做预先的处理,那么将来程序崩溃就无从调试,很难找到异常所在的位置.本文将探讨一下Java中异常与错误的处理 ...