[洛谷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, ...
随机推荐
- Iptables用法规则及防火墙配置
[转载]http://www.cnblogs.com/yi-meng/p/3213925.html iptables规则 即防火墙规则,在内核看来,规则就是决定如何处理一个包的语句.如果一个包符合条 ...
- python机器学习(1:K_means聚类算法)
一.算法介绍 K-means算法是最简单的也是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的.算法的目的是使各个样本与所在均值的误差平方和达到最小(这也是评价K-means算 ...
- Linux-竟态初步引入
(1).竟态全称是:竞争状态,多进程环境下,多个进程同时抢占系统资源(内存.CPU.文件IO). (2).竞争状态对于操作系统OS来说是很危险的,此时的操作系统OS如果没有处理好就会造成结果不确定. ...
- jupyter notebook的扩展插件
具体安装使用,请参考 https://github.com/ipython-contrib/IPython-notebook-extensions
- mysql字段修改脚本
-- help_text:帮助说明 -- help_content -- raw USE pro_seal_chip_sell_portal_v1; -- 表修改ALTER TABLE `help_t ...
- Underscore _.template 方法使用详解
为什么用「void 0」代替「undefined」 undefined 并不是保留词(reserved word),它只是全局对象的一个属性,在低版本 IE 中能被重写. 事实上,undefined ...
- C语言中“段错误”出现的场景
1.第一种“段错误”出现的场景 1 /************************************************************************* > Fi ...
- 可用的 .net core 支持 RSA 私钥加密工具类
首先说明 MS并不建议私钥加密,而且.net 于安全的考虑,RSACryptoServiceProvider类解密时只有同时拥有公钥和私钥才可以,原因是公钥是公开的,会被多人持有,这样的数据传输是不安 ...
- UI自动化(selenium+python)之浏览器驱动chromedriver安装和配置
一.安装selenium 前提是已安装Python,python安装 自行百度,这里不概述 安装好python后,cmd打开终端窗口-->pip命令安装 :pip install seleniu ...
- Nginx_配置文件解读及模板
Nginx 介绍 # nginx的最大优势在于处理静态文件和代理转发功能,支持7层负载均衡和故障隔离. 动静分离是每个网站发展到一定规模之后必然的结果.静态请求则应当最好将其拆分,并启用独立的域名,既 ...