[Vani有约会]雨天的尾巴(树上差分+线段树合并)
首先村落里的一共有n座房屋,并形成一个树状结构。然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。
Solution
一看到链上操作,最后统计答案,自然而然的想到树上差分,a++ ,b++,lca--,fa[lca]--就可以完成一条链的操作。
但这道题加的东西有好多种类。
所以考虑对每个节点开一颗线段树,每次在对应位置加上。
然后我们DFS的时候,朴素的树上差分直接size[u]+=size[v] (son[u]==v)这回u和v是两颗线段树。
所以用线段数合并就行了。
由于这题涉及大量的线段树,所以我们的数组得开大点。
颜色需要提前离散化。
Code
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #define N 100002
- using namespace std;
- int p[N][],head[N],tot,deep[N],tr[N*],L[N*],R[N*],num[N],rt[N],top,ans[N],toy;
- struct zzh{
- int n,to;
- }e[N<<];
- struct bi{
- int a,b,d;
- }q[N];
- inline void add(int u,int v){
- e[++tot].n=head[u];
- e[tot].to=v;
- head[u]=tot;
- }
- void dfs(int u,int fa){
- for(int i=;(<<i)<=deep[u];++i)p[u][i]=p[p[u][i-]][i-];
- for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
- int v=e[i].to;p[v][]=u;deep[v]=deep[u]+;
- dfs(v,u);
- }
- }
- inline int getlca(int a,int b){
- if(deep[a]<deep[b])swap(a,b);
- for(int i=;i>=;--i)if(deep[a]-(<<i)>=deep[b])a=p[a][i];
- if(a==b)return a;
- for(int i=;i>=;--i)if(p[a][i]!=p[b][i])a=p[a][i],b=p[b][i];
- return p[a][];
- }
- void upd(int &cnt,int l,int r,int x,int y){
- if(!cnt)cnt=++toy;
- if(l==r){
- tr[cnt]+=y;
- return;
- }
- int mid=(l+r)>>;
- if(mid>=x)upd(L[cnt],l,mid,x,y);
- else upd(R[cnt],mid+,r,x,y);
- tr[cnt]=max(tr[L[cnt]],tr[R[cnt]]);
- }
- int query(int &cnt,int l,int r){
- if(!tr[cnt]||!cnt)return ;
- if(l==r)return num[l];
- int mid=(l+r)>>;
- if(tr[L[cnt]]>=tr[R[cnt]])return query(L[cnt],l,mid);
- else return query(R[cnt],mid+,r);
- }
- int merge(int &u,int v,int l,int r){
- if(!u||!v)return u+v;
- if(l==r){
- tr[u]+=tr[v];
- return u;
- }
- int mid=(l+r)>>;
- L[u]=merge(L[u],L[v],l,mid);
- R[u]=merge(R[u],R[v],mid+,r);
- tr[u]=max(tr[L[u]],tr[R[u]]);
- return u;
- }
- void dfs2(int u,int fa){
- for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
- int v=e[i].to;
- dfs2(v,u);
- rt[u]=merge(rt[u],rt[v],,top);
- }
- ans[u]=query(rt[u],,top);
- }
- int main(){
- int n,m,u,v;
- scanf("%d%d",&n,&m);
- for(int i=;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u);
- dfs(,);
- for(int i=;i<=m;++i)scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].d),num[++top]=q[i].d;
- sort(num+,num+top+);
- top=unique(num+,num+top+)-num-;
- for(int i=;i<=m;++i){
- q[i].d=lower_bound(num+,num+top+,q[i].d)-num;
- int lca=getlca(q[i].a,q[i].b);
- upd(rt[q[i].a],,top,q[i].d,);upd(rt[q[i].b],,top,q[i].d,);
- upd(rt[lca],,top,q[i].d,-);upd(rt[p[lca][]],,top,q[i].d,-);
- }
- dfs2(,);
- for(int i=;i<=n;++i)printf("%d\n",ans[i]);
- return ;
- }
[Vani有约会]雨天的尾巴(树上差分+线段树合并)的更多相关文章
- BZOJ 3307 雨天的尾巴 (树上差分+线段树合并)
题目大意:给你一棵树,树上一共n个节点,共m次操作,每次操作给一条链上的所有节点分配一个权值,求所有节点被分配到所有的权值里,出现次数最多的权值是多少,如果出现次数相同就输出最小的. (我辣鸡bzoj ...
- [Vani有约会]雨天的尾巴——树上差分+动态开点线段树合并
题目描述 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所 ...
- [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)
[BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...
- [Luogu5327][ZJOI2019]语言(树上差分+线段树合并)
首先可以想到对每个点统计出所有经过它的链的并所包含的点数,然后可以直接得到答案.根据实现不同有下面几种方法.三个log:假如对每个点都存下经过它的链并S[x],那么每新加一条路径进来的时候,相当于在路 ...
- 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)
传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...
- P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (树上差分+线段树合并)
显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/st ...
- bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)
Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后,每个点存放最多的是哪种物品. Input ...
- bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】
这居然是我第一次写线段树合并--所以我居然在合并的时候加点结果WAWAWAMLEMLEMLE--!ro的时候居然直接指到la就行-- 树上差分,每个点建一棵动态开点线段树,然后统计答案的时候合并即可 ...
- 【bzoj3307】雨天的尾巴 权值线段树合并
题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y,对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来 ...
- Luogu5327 ZJOI2019语言(树上差分+线段树合并)
暴力树剖做法显然,即使做到两个log也不那么优美. 考虑避免树剖做到一个log.那么容易想到树上差分,也即要对每个点统计所有经过他的路径产生的总贡献(显然就是所有这些路径端点所构成的斯坦纳树大小),并 ...
随机推荐
- MySQL dump文件导入
1 打开cmd 输入要导入的数据库,用户名,密码,dump文件路径 mysql -u employees <E:\employees_db\load_departments.dump
- 【转帖】远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm) https://zhuanlan.zhihu.com/p/310 ...
- linux关闭触摸板
关闭触摸板 sudo modprobe -r psmouse 如果打开触摸板就是: sudo modprobe psmouse
- 在linux上安装MySQL数据库,并简单设置用户密码,登录MySQL
在新装的Centos系统上安装MySQL数据库. <p><a href="http://www.cnblogs.com/tijun/">提君博客原创< ...
- 谈谈git/github
先说git/github操作 ->关于git/github操作的好文章已经非常多,如: github使用指南 廖雪峰的git教程 本文的目的在于,积累自己平时相关的操作和想法,记录下来,形成自己 ...
- 关于golang.org/x包问题
关于golang.org/x包问题 由于谷歌被墙,跟谷歌相关的模块无法通过go get来下载,解决方法: git clone https://github.com/golang/net.git $GO ...
- 详解 RestTemplate 操作
转载自:https://blog.csdn.net/itguangit/article/details/78825505 作为开发人员,我们经常关注于构建伟大的软件来解决业务问题.数据只是软件完成工作 ...
- orcale建表脚本
declare v_cnt number; V_SQL VARCHAR2 (500) := '';begin select count(*) into v_cnt from dual where ex ...
- extensions
extensions.blocklist.enabled
- openblas下载安装编译
编译好的库: https://github.com/JuliaLinearAlgebra/OpenBLASBuilder/releases 源码编译 下载:https://github.com/xia ...