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

但是为什么我就偏偏要用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. UML-类图-构造型应用场景是什么?

    1.什么是构造型? 抽象出来的标准的模型元素. 2.有哪些? 1.预定义的,如:<<destory>> 2.自定义的 3.自定义

  2. The mplot3d Toolkit

    简介 正如,pyplot模块被用来绘制二维图,matplotlib使用mplot3d模块绘制三维图形,在mplot3d模块中存在 mpl_toolkits.mplot3d.axes3dmpl_tool ...

  3. SpringBoot2中,怎么生成静态文档

    SpringBoot2中,怎么生成静态文档 在实际开发过程中,我们通过swagger就可以生成我们的接口文档,这个文档就可以提供给前端人员开发使用的.但是,有时候,我们需要把我们的接口文档,提供给第三 ...

  4. PID<->Port[转]

    //Netstat -anb #include <Windows.h> #include "Psapi.h" #include <Iprtrmib.h> # ...

  5. 小白学习之pytorch框架(5)-多层感知机(MLP)-(tensor、variable、计算图、ReLU()、sigmoid()、tanh())

    先记录一下一开始学习torch时未曾记录(也未好好弄懂哈)导致又忘记了的tensor.variable.计算图 计算图 计算图直白的来说,就是数学公式(也叫模型)用图表示,这个图即计算图.借用 htt ...

  6. Win10用Windows照片查看程序(照片查看器)打开图片

    以上方法只能一个个添加,也有人说不好使,这里给出一个我写的批处理程序,反正我一直用着很好.   ::复制以下内容到记事本: @echo off&cd\&color 0a&cls ...

  7. Andorid Studio 3.1 引入第三方jar包的方法

    今天手痒,把android studio 从3.0升级到3.1.2 发现很多问题 1.发现编译会下载好多东西,等半天 2.之前的jar包导不进来了 针对jar包导入不成功,我查了一下说是不支撑comp ...

  8. spring02-组件注册-@ComponentScan-自动扫描组件&指定扫描规则

    上一篇我们讲到,讲@Bean注解标在某个方法上,那么ioc容器启动的时候就会将方法返回值放到ioc容器中 在开发中,实际上包扫描用的比较多,接下来我们会介绍两种方式一种是基于xml,一种是基于注解. ...

  9. Codeforces 1292B/1293D - Aroma's Search

    题目大意: Aroma想要找数据第0个数据再x0,y0这个点其后所有数据所在的坐标点满足x[i]=x[i-1]*ax+bxy[i]=y[i-1]*ay+byAroma一开始在点(xs,ys),她最多只 ...

  10. 21)PHP,杨辉三角

    代码展示: $n=; ;$i<=$n;$i++){ ;$k<=$i;$k++){ ||$k==$i){ $arr[$i][$k]=; }else{ ){ $arr[$i][$k] = $a ...