P4556 雨天的尾巴 线段树合并
使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标)。所以每个节点答案即为\(tre[rot[x]]\)。
然后运用树上点的差分思想,对于分发路径\(u,v\),我们在\(u\)上+1,在\(v\)+1,在\(lca(u,v)\)处-1,在\(fa(lca)\)处-1,最后统计时自底向上做树上前缀和、线段树合并即得当前节点信息。
需要注意的是,在合并时可能会出现\(tre[rot[x]]\)不为\(0\),但是\(sum[rot[x]]\)为\(0\)的情况,这时候表示编号为\(tre[rot[x]]\)的救济粮数量为\(0\),所以此时应该将\(ans[x]\)更新为\(0\)(根据题意)。
#include <cstdio>
#include <algorithm>
#define MAXN 100001
#define LOG 19
#define mxr 100000
using namespace std;
inline int read(){
char ch=getchar();int s=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+(ch^'0'),ch=getchar();
return s;
}
int head[MAXN],nxt[MAXN*2],vv[MAXN*2],tot;
inline void add_edge(int u, int v){
vv[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int n,m;
#define MAXM MAXN*80
int tre[MAXM],sum[MAXM],sl[MAXM],sr[MAXM],cnt;
void push_up(int x){
if(sl[x]==0){
sum[x]=sum[sr[x]];
tre[x]=tre[sr[x]];
return;
}
if(sr[x]==0){
sum[x]=sum[sl[x]];
tre[x]=tre[sl[x]];
return;
}
if(sum[sl[x]]>=sum[sr[x]]){
sum[x]=sum[sl[x]];
tre[x]=tre[sl[x]];
}else{
sum[x]=sum[sr[x]];
tre[x]=tre[sr[x]];
}
}
void change(int &x, int l, int r, int pos, int val){
if(x==0) x=++cnt;
if(l==r){
sum[x]+=val;
tre[x]=pos;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) change(sl[x], l, mid, pos, val);
else change(sr[x], mid+1, r, pos, val);
push_up(x);
}
int merge(int a, int b, int l, int r){
if(a==0||b==0) return a+b;
if(l==r){
sum[a]+=sum[b];
return a;
}
int mid=(l+r)>>1;
sl[a]=merge(sl[a], sl[b], l, mid);
sr[a]=merge(sr[a], sr[b], mid+1, r);
push_up(a);
return a;
}
int f[MAXN][LOG],dep[MAXN];
void dfs(int u, int fa){
f[u][0]=fa;
dep[u]=dep[fa]+1;
for(int i=1;i<LOG;++i)
f[u][i]=f[f[u][i-1]][i-1];
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==fa) continue;
dfs(v, u);
}
}
int lca(int a, int b){
if(dep[a]<dep[b]) swap(a, b);
for(int i=LOG-1;i>=0;--i)
if(dep[f[a][i]]>=dep[b])
a=f[a][i];
if(a==b) return a;
for(int i=LOG-1;i>=0;--i)
if(f[a][i]!=f[b][i])
a=f[a][i],b=f[b][i];
return f[a][0];
}
int rot[MAXN],ans[MAXN];
void calc(int u, int fa){
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==fa) continue;
calc(v, u);
rot[u]=merge(rot[u], rot[v], 1, mxr);
}
ans[u]=tre[rot[u]];
if(sum[rot[u]]==0) ans[u]=0; // 特判没有救济粮的情况
}
int main(){
n=read(),m=read();
for(int i=1;i<n;++i){
int a=read(),b=read();
add_edge(a, b);
add_edge(b, a);
}
dfs(1, 0);
for(int i=1;i<=m;++i){
int a=read(),b=read(),x=read();
int l=lca(a, b);
change(rot[a], 1, mxr, x, 1);
change(rot[b], 1, mxr, x, 1);
change(rot[l], 1, mxr, x, -1);
change(rot[f[l][0]], 1, mxr, x, -1);
}
calc(1, 0);
for(int i=1;i<=n;++i) printf("%d\n", ans[i]);
return 0;
}
P4556 雨天的尾巴 线段树合并的更多相关文章
- [Vani有约会]雨天的尾巴 线段树合并
[Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...
- 【BZOJ3307】雨天的尾巴 线段树合并
[BZOJ3307]雨天的尾巴 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多 ...
- BZOJ3307雨天的尾巴——线段树合并
题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来N ...
- 洛谷P4556 雨天的尾巴 线段树
正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...
- bzoj 3307: 雨天的尾巴 线段树合并
题目大意: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.问完成所有发放后,每个点存放最多的是哪种物品. 题解: 首先我们为每一个节 ...
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- [BZOJ3307] 雨天的尾巴-----------------线段树进阶
虽然是个板子,但用到了差分思想. Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最 ...
- 洛谷P4556 雨天的尾巴(线段树合并)
洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...
- P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)
P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...
随机推荐
- Scratch零基础起步攻略(一)
通常,类似这样的文章开头总要阐述一大段关于编程的重要性,还有自己的专业性.权威性等等,我就都省掉了…… 简单介绍一下自己,从事计算机编程教育前前后后有近20年了,面对了不同年龄层次的学员,大部分跟着我 ...
- Scratch编程:多彩的舞台(六)
“ 上节课的内容全部掌握了吗?反复练习了没有,编程最好的学习方法就是练习.练习.再练习.一定要记得多动手.多动脑筋哦~~” 01 — 游戏介绍 这是一款简单的小游戏,实现了一个小女孩在多彩的舞台上进行 ...
- javascript-state-machine
import StateMachine from 'javascript-state-machine' import EventEmitter from 'events' /** * 上传的文档的状态 ...
- ivew数控件Tree自定义节点内容示例分析
ivew数控件Tree自定义节点内容示例分析 demo地址:https://run.iviewui.com/plcWlM4H <template> <Tree :data=" ...
- VBA While Wend循环
在While...Wend循环中,如果条件为True,则会执行所有语句,直到遇到Wend关键字. 如果条件为false,则退出循环,然后控件跳转到Wend关键字后面的下一个语句. 语法 以下是VBA中 ...
- php协议任意文件读取
php://filter/read=convert.base64-encode/resource=index.php
- jar找不到问题解决
1.File->Settings->搜maven->看Local repository的路径配置是否正确,再看User settings file路径配置是否正确,再看xml内容配置 ...
- Linux软件包(源码包和二进制包)及其区别和特点
Linux 下的软件包众多,而且几乎都是经 GPL 授权的,也就是说这些软件都免费,振奋人心吧?而且更棒的是,这些软件几乎都提供源代码(开源的),只要你愿意,就可以修改程序源代码,以符合个人的需求和习 ...
- django操作mysql
连接mysql 1.安装pymysql 操作指令 : pymsql: pip install pymysql 2.导入库 在项目目录下的__init__.py文件中导入pymysql模块 加入以下两行 ...
- 解决用Xftp向虚拟机VMware传文件速度慢的问题
在使用Xftp向虚拟机传文件时发现很慢,之后几K,如果这个文件有几十M,这是一个非常让人头疼的问题.网上找过很多设置都试过,都没有效果,偶然发现Windows网络配置中,有个选项Large Send ...