题目背景

深绘里一直很讨厌雨天。

灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。


虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。


无奈的深绘里和村民们只好等待救济粮来维生。


不过救济粮的发放方式很特别。

题目描述

首先村落里的一共有n座房屋,并形成一个树状结构。然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮。

然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。

输入输出格式

输入格式:

第一行两个正整数n,m,含义如题目所示。

接下来n-1行,每行两个数(a,b),表示(a,b)间有一条边。


再接下来m行,每行三个数(x,y,z),含义如题目所示。

输出格式:

n行,第i行一个整数,表示第i座房屋里存放的最多的是哪种救济粮,如果有多种救济粮存放次数一样,输出编号最小的。

如果某座房屋里没有救济粮,则对应一行输出0。

输入输出样例

输入样例#1:
复制

5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
输出样例#1: 复制

2
3
3
0
2

说明

对于20%的数据,1 <= n, m <= 100

对于50%的数据,1 <= n, m <= 2000


对于100%的数据,1 <= n, m <= 100000, 1 <= a, b, x, y <= n, 1 <= z <= 100000


Vani

题解:这题的话主要是差分的思想,把每条覆盖路径离线下来,分解成(u,lca(u,v))(u,lca(u,v))(u,lca(u,v)),(v,lca(u,v))(v,lca(u,v))(v,lca(u,v))两条路径,在uuu点和vvv点将zzz位置+1+1+1,在lca(u,v)lca(u,v)lca(u,v)和fa(lca(u,v))fa(lca(u,v))fa(lca(u,v))的位置分别−1-1−1就可以了。每个点直接查询最大值,即为答案。

代码如下:

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson tr[now].l
#define rson tr[now].r
using namespace std; struct tree
{
int l,r,sum,val;
}tr[]; int n,m,deep[],a[],cnt,rt[],fa[][],ans[];
vector<int> g[];
vector<int> op1[],op2[]; int dfs(int now,int f,int dep)
{
fa[now][]=f;
deep[now]=dep;
rt[now]=now;
cnt++;
for(int i=;i<=;i++)
{
fa[now][i]=fa[fa[now][i-]][i-];
}
for(int i=;i<g[now].size();i++)
{
if(g[now][i]==f) continue;
dfs(g[now][i],now,dep+);
}
} int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
for(int i=;i>=;i--) if(deep[fa[x][i]]>=deep[y]) x=fa[x][i];
if(x==y) return y;
for(int i=;i>=;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
} int push_up(int now)
{
if(tr[rson].sum>tr[lson].sum)
{
tr[now].sum=tr[rson].sum;
tr[now].val=tr[rson].val;
}
else
{
tr[now].sum=tr[lson].sum;
tr[now].val=tr[lson].val;
}
} int update(int &now,int l,int r,int pos,int v)
{
if(!now) now=++cnt;
if(l==r)
{
tr[now].sum+=v;
tr[now].val=l;
return ;
}
int mid=(l+r)>>;
if(pos<=mid) update(lson,l,mid,pos,v);
else update(rson,mid+,r,pos,v);
push_up(now);
} int merge(int now,int a,int l,int r)
{
if(!now) return a;
if(!a) return now;
if(l==r)
{
tr[now].sum+=tr[a].sum;
tr[now].val=l;
return now;
}
int mid=(l+r)>>;
lson=merge(lson,tr[a].l,l,mid);
rson=merge(rson,tr[a].r,mid+,r);
push_up(now);
return now;
} int dfs2(int now,int f)
{
for(int i=;i<g[now].size();i++)
{
if(g[now][i]==f) continue;
dfs2(g[now][i],now);
merge(rt[now],rt[g[now][i]],,);
}
for(int i=;i<op1[now].size();i++)
{
update(rt[now],,,op1[now][i],);
}
for(int i=;i<op2[now].size();i++)
{
update(rt[now],,,op2[now][i],-);
}
ans[now]=tr[rt[now]].val;
} int main()
{
scanf("%d%d",&n,&m);
int from,to,cost;
for(int i=;i<n;i++)
{
scanf("%d%d",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
dfs(,,);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&from,&to,&cost);
int ttt=lca(from,to);
op1[from].push_back(cost);
op1[to].push_back(cost);
op2[ttt].push_back(cost);
if(fa[ttt][]) op2[fa[ttt][]].push_back(cost);
}
dfs2(,);
for(int i=;i<=n;i++)
{
printf("%d\n",ans[i]);
}
}

这题的话主要是差分的思想,把每条覆盖路径离线下来,分解成(u,lca(u,v))(u,lca(u,v))(u,lca(u,v)),(v,lca(u,v))(v,lca(u,v))(v,lca(u,v))两条路径,在uuu点和vvv点将zzz位置+1+1+1,在lca(u,v)lca(u,v)lca(u,v)和fa(lca(u,v))fa(lca(u,v))fa(lca(u,v))的位置分别−1-1−1就可以了。每个点直接查询最大值,即为答案。

洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)的更多相关文章

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

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

  2. [Vani有约会]雨天的尾巴 线段树合并

    [Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...

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

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

  4. 洛谷4556 [Vani有约会]雨天的尾巴

    原题链接 每个点开一个权值线段树,然后用树上差分的方法修改,最后自底向上暴力线段树合并即可. 不过空间较大,会\(MLE\),写个内存池就可以了. #include<cstdio> #in ...

  5. 洛咕 P4556 [Vani有约会]雨天的尾巴

    终于把考试题清完了...又复活了... 树上差分,合并用线段树合并,但是空间会炸. 某大佬:lca和fa[lca]减得时候一定已经存在这个节点了,所以放进vector里,合并完之后减掉就好了... 玄 ...

  6. P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)

    P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...

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

    P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋 ...

  8. [题解] P4556 [Vani有约会]雨天的尾巴

    [题解] P4556 [Vani有约会]雨天的尾巴 ·题目大意 给定一棵树,有m次修改操作,每次修改 \(( x\) \(y\) \(z )\) 表示 \((x,y)\) 之间的路径上数值 \(z\) ...

  9. 【BZOJ3307】雨天的尾巴 线段树合并

    [BZOJ3307]雨天的尾巴 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多 ...

随机推荐

  1. MoveWindow() SetWindowPos()的区别于联系

    敲代码时,突然发现有一个背景图片无法显示,百思不得其解,最终发现是MoveWindow() SetWindowPos()这两个函数的使用不当造成的. 这里把这两个函数的前世今生给分析一下. 先看Mov ...

  2. SQL 知识及用法备忘录

    ---查询当前数据库一共有多少张表 ) from sysobjects where xtype='U' ---查询当前数据库有多少张视图 ) from sysobjects where xtype=' ...

  3. jmeter录制https请求时,浏览器每一个请求都 跳 不安全访问页面的解决方法

    1.关闭所有浏览器 2,使用终端 输入 : /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --ignore-certif ...

  4. CentOS–root密码忘记的解决办法

    一.重启系统,如图:GRUB: 在引导装载程序菜单上,用上下方向键选择你忘记密码的那个系统键入“e”  来进入编辑模式.   2.接下来你可以看到如下图所示的画面,然后你再用上下键选择最新的内核(这里 ...

  5. jQuery ajax 当async为false时解决同步操作失败的问题

    jQuery的ajax,当async为false时,同步操作失败.解决方案,jqueryasync 最近做项目遇到jQuery的ajax,当async为false时,同步操作失败的问题,上网搜索下,得 ...

  6. 接口自动化(六)--使用QQ邮箱发送邮件

    接口测试执行完发送一个邮件,这里使用QQ邮箱发送,先要拿到QQ邮箱授权码,方法自行百度 # coding=utf-8 import smtplib from email.mime.text impor ...

  7. 网络通信和TCP详解

    交换机.路由器.服务器组网 1. 通信过程(pc+switch+router+server) 较为复杂的通信过程如:访问 www.baidu.com 注意:一定要配置 PC:IP.NETMASK.DF ...

  8. 好记性不如烂笔头--linux学习笔记8关于nginx的动静分离

    动静分离逻辑梳理 就是给nginx配置访问规则,不同后缀的文件访问不同的目录 worker_processes 1; events { worker_connections 1024; } http ...

  9. 使用打印方法时,要先引用命名空间: Using System.Drawing.Pringing

    使用打印方法时,要先引用命名空间: Using System.Drawing.Pringing PrintDocument类的重要属性和方法:属性:DocumentName  设置打印文档时要显示的文 ...

  10. Halcon中二维码解析函数解码率和时长的优化方法

    Halcon中条码解析函数包容多种条码类型且简单强大.现有的‘Data Matrix ECC 200’.‘QR Code’和‘PDF417’等广泛使用的条码均能解析.简单是通过默认参数即可对多种条码进 ...