[洛谷P4556] 雨天的尾巴
这道题可以用线段树合并做,网上的题解基本上都是线段树合并的。
但是为什么我就偏偏要用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] 雨天的尾巴的更多相关文章
- 洛谷P4556 雨天的尾巴(线段树合并)
洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...
- 洛谷P4556 雨天的尾巴 线段树
正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...
- [洛谷 P4556] 雨天的尾巴
传送门 Solution 线段树合并的入门题 lca可以在dfs的时候离线求(用并查集) 更新的点有每条链的两个端点,它们的lca和dad[lca] 为了节省空间,lca和dad[lca]的更新可以先 ...
- 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告
P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)
传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...
- 【洛谷P4556】 雨天的尾巴
题面 题解 线段树合并 我们看到这道题目首先可以想到树上差分,然后\(dfs\)合并 发现题目让我们求的东西很好用线段树维护 于是可以想到线段树合并 全世界只有我写指针版动态开点线段树(大雾 如果你要 ...
- [洛谷P4556][BZOJ3307]雨天的尾巴-T3订正
线段树合并+树上差分 题目链接(···) 「简单」「一般」——其实「一般」也只多一个离散化 考试时想法看>这里< 总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每 ...
- P4556 雨天的尾巴 线段树合并
使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u, ...
随机推荐
- openvino资源
Intel OpenVINO介紹及樹莓派.Linux的安裝 https://chtseng.wordpress.com/2019/01/21/intel-openvino%E4%BB%8B%E7%B4 ...
- Django框架(一):MVC设计模式、Django简介
1. MVC设计模式 MVC设计模式:Model-View-Controller简写. 最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪8 ...
- shell手册
摘自雪松同学 0说明{ # shell实例手册最新下载地址: http://hi.baidu.com/quanzhou722/item/f4a4f3c9eb37f02d46d5c0d9 # pytho ...
- 使script.bin文件配置生效的驱动
1.问题:在全志方案中如果需要设置上拉或者下拉模式,需要在script.bin(先转换为script.fex)中配置gpio口 如: 但是配置好后是不会生效的,需要写一个驱动来通过读取这个文件的gp ...
- 使用idea创建spring mvc项目图文教程
使用idea创建spring mvc项目图文教程 前言: 使用惯了eclipse的朋友,如果刚换成了idea或许有些不习惯.但是使用idea之后,就会love上idea了.本文将通过图文讲解怎么通过i ...
- Prefix and Suffix
题目描述 Snuke is interested in strings that satisfy the following conditions: The length of the string ...
- mac下停止和启动mysql命令
启动MySQL服务 sudo /usr/local/MYSQL/support-files/mysql.server start 停止MySQL服务 sudo /usr/local/mysql/s ...
- [LC] 234. Palindrome Linked List
Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false ...
- 3dmax2019卸载/安装失败/如何彻底卸载清除干净3dmax2019注册表和文件的方法
3dmax2019提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装3dmax2019失败提示3dmax2019安装未完成,某些产品无法安装,也有时候想重新安装3 ...
- 深入探讨Java中的异常与错误处理
Java中的异常处理机制已经比较成熟,我们的Java程序到处充满了异常的可能,如果对这些异常不做预先的处理,那么将来程序崩溃就无从调试,很难找到异常所在的位置.本文将探讨一下Java中异常与错误的处理 ...