bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)
Description
N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。
Input
第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题
Output
输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0
看到对树上路径进行操作,(以蒟蒻博主目前的知识水平)无非两个选择,树剖/树上差分
但是最后只询问一次的话差分会是更好的选择
而且我们要进行的操作并非只是对点的权值进行更改,而是对于每个点插入新的权值并统计出众数
这时候应该想到在每一个节点建权值线段树来维护信息
这样差分的操作就利用权值线段树的插入操作解决了
然鹅在最后统计的时候要合并子树信息
所以还需要线段树合并
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=;
int n,m,to[N<<],nxt[N<<],head[N],tot=;
int size[N*],type,root[N],ls[N*],rs[N*],fa[N][],dep[N],now[N*],ans[N];
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>'')
{if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')
{x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
}
void dfs(int x,int deep)
{
dep[x]=deep;
for(int i=;i<=;i++)
fa[x][i]=fa[fa[x][i-]][i-];
for(int i=head[x];i;i=nxt[i])
{
if(dep[to[i]])continue;
fa[to[i]][]=x;
dfs(to[i],deep+);
}
}
int lca(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
for(int i=;i>=;i--)
if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
if(x==y)return x;
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][];
}
void up(int x)
{
if(size[ls[x]]>=size[rs[x]])
{
size[x]=size[ls[x]];
now[x]=now[ls[x]];
}
else
{
size[x]=size[rs[x]];
now[x]=now[rs[x]];
}
}
void update(int &k,int l,int r,int val,int num)
{
if(!k)k=++type;
if(l==r)
{
size[k]+=num;
now[k]=l;
return ;
}
int mid=l+r>>;
if(val<=mid)update(ls[k],l,mid,val,num);
else update(rs[k],mid+,r,val,num);
up(k);
return ;
}
int Merge(int x,int y,int l,int r)
{
if(!x||!y)return x+y;
if(l==r)
{
size[x]=size[x]+size[y];
now[x]=l;
return x;
}
int mid=l+r>>;
ls[x]=Merge(ls[x],ls[y],l,mid);
rs[x]=Merge(rs[x],rs[y],mid+,r);
up(x);
return x;
}
void cacl(int x)
{
for(int i=head[x];i;i=nxt[i])
{
if(to[i]==fa[x][])continue;
cacl(to[i]);
root[x]=Merge(root[x],root[to[i]],,N-);
}
if(now[root[x]])ans[x]=now[root[x]];
else ans[x]=;
}
int main()
{
n=read();m=read();
for(int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs(,);
for(int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
int LCA=lca(x,y);//cout<<"///"<<LCA<<endl;
update(root[x],,N-,z,);
update(root[y],,N-,z,);
update(root[LCA],,N-,z,-);
update(root[fa[LCA][]],,N-,z,-);
}
cacl();
for(int i=;i<=n;i++)printf("%d\n",ans[i]);
return ;
}
bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)的更多相关文章
- BZOJ_3307_雨天的尾巴_线段树合并+树上差分
BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...
- Bzoj 3307 雨天的尾巴(线段树合并+树上差分)
C. 雨天的尾巴 题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第 ...
- [bzoj3307]雨天的尾巴_线段树合并
雨天的尾巴 bzoj-3307 题目大意:N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. ...
- 雨天的尾巴(bzoj3307)(线段树合并+树上差分)
\(N\)个点,形成一个树状结构.有\(M\)次发放,每次选择两个点\(x,y\) 对于\(x\)到\(y\)的路径上(含\(x,y\))每个点发一袋\(Z\)类型的物品.完成 所有发放后,每个点存放 ...
- P4556 [Vani有约会]雨天的尾巴 (线段树合并)
P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋 ...
- BZOJ 3307: 雨天的尾巴( LCA + 线段树合并 )
路径(x, y) +z : u处+z, v处+z, lca(u,v)处-z, fa(lca)处-z, 然后dfs一遍, 用线段树合并. O(M log M + M log N). 复杂度看起来不高, ...
- P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)
P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...
- P4556 [Vani有约会]雨天的尾巴(线段树合并)
传送门 一道线段树合并 首先不难看出树上差分 我们把每一次修改拆成四个,在\(u,v\)分别放上一个,在\(lca\)和\(fa[lca]\)各减去一个,那么只要统计一下子树里的总数即可 然而问题就在 ...
- 洛谷P4556 雨天的尾巴(线段树合并)
洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...
随机推荐
- Filter的基本配置
1.<dispatcher></dispatcher>节点:指定过滤器所拦截的servlet容器调用资源的方式,有REQUEST,INCLUDE,FORWARD,ERROR,默 ...
- k8s-容器资源需求、资源限制及HeapSter-二十二
一.容器资源需求.资源限制 资源需求.资源限制:指的是cpu.内存等资源: 资源需求.资源限制的两个关键字: request:需求,最低保障,在调度时,这个节点必须要满足request需求的资源大小: ...
- Gradle系列之一 Groovy语法精讲
Gradle技术之一 Groovy语法精讲 gradle脚本是基于groovy语言开发的,想要学好gradle必须先要对groovy有一个基本的认识 1. Groovy特点 groovy是一种DSL语 ...
- Codeforces - 706B - Interesting drink - 二分 - 简单dp
https://codeforces.com/problemset/problem/706/B 因为没有看见 $x_i$ 的上限是 $10^5$ ,就用了二分去做,实际上这道题因为可乐的价格上限是 $ ...
- 腾讯QQ团队开源分布式后台毫秒服务引擎全解析:引擎架构、RPC、灰度……
腾讯QQ团队将于12月4日开源一个服务开发运营框架,叫做毫秒服务引擎(Mass Service Engine in Cluster,MSEC),它集RPC.名字发现服务.负载均衡.业务监控.灰度发布. ...
- SVG动画 -- 描边动画
代码说明:纯CSS实现,无JS <!DOCTYPE html> <html lang="en"> <head> <meta charset ...
- 【CodeForces - 546C】Soldier and Cards (vector或队列)
Soldier and Cards 老样子,直接上国语吧 Descriptions: 两个人打牌,从自己的手牌中抽出最上面的一张比较大小,大的一方可以拿对方的手牌以及自己打掉的手牌重新作为自己的牌, ...
- NOIp 2015信息传递【tarjan/拓扑/并查集】
一道好的NOIp题目,在赛场上总能用许多算法A掉.比如这道和关押罪犯. 题目传送门 法一:tarjan在有向图中跑最小环 有人从别人口中得知自己信息,等效于出现了一个环.于是 这就变成了一个有向图ta ...
- Centos 6.x 搭建 Zabbix Server
zabbix(音同 zæbix)是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让 ...
- WIN7 64位操作系统 无法找到Access驱动
为了更充分的利用硬件资源,我想很多人都开使用64位操作系统了,同时你可以也发现了在64位操作系统上ODBC的驱动找不到了,所以ODBC的东西都没法用了. 因为2007以前版本的Office只有32位版 ...