题目描述

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

----------------------------------van美分界线----------------------------------

先%一发pa大佬考试A掉这题

%%%pa

考试时刚看到这题时觉得和之前的考试题松鼠的新家(此坑未填)很像,因为都是对树上的一条链进行修改操作

所以很容易想到树上差分(其实树剖也可以但蒟蒻博主并不会),具体讲就是将链的两端加一,将lca和lca父亲节点减一。

然后我们可以看到他是询问数量所以可以想到在每一个节点建一棵权值线段树来维护信息。

又看到1e9的范围瞬间吓尿,跑去码T1,其实只要离散化一下就可以,因此我们不仅需要维护每一个节点的最大值,还要维护最大值出现的位置,这样比较方便输出答案,建立对应关系即可。

最后dfs统计答案即可,就是从叶节点往上不断merge。

最后要注意的一点就是和线段树有关的数组一定要开大一些,本人亲测要1e5×60,临接表数组开二倍(都这时候了我还犯这么低级错误,真沙雕)。

回想一下这题也没那么难,但我还是断断续续调了得有5.6节课,沙雕错误百出。具体沙雕错误代码里都有注释(大佬自动忽略即可,勿喷)。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+;
int n,m;int tot;int t;
int first[N],nex[N*],to[N*],cnt,d[N],root[N**],v[N],f[N][],sum[N**],posm[N**],ls[N**],rs[N**],ans[N],x[N],yy[N],zz[N],num[N];
void add(int a,int b){
to[++tot]=b;nex[tot]=first[a];first[a]=tot;
}
void bfs(int x){
queue<int> q;
q.push(x);d[x]=;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(d[y]) continue;
d[y]=d[x]+;
f[y][]=x;
for(int j=;j<=t;j++)
f[y][j]=f[f[y][j-]][j-];
q.push(y);
}
}
}
int Lca(int x,int y){
if(d[y]<d[x]) swap(x,y);
for(int i=t;i>=;i--){
if(d[f[y][i]]>=d[x]) y=f[y][i];
}
if(x==y) return x;
for(int i=t;i>=;i--){
if(f[y][i]!=f[x][i]) x=f[x][i],y=f[y][i];
}
return f[x][];
}
void pushup(int x){
if(sum[ls[x]]>=sum[rs[x]]) sum[x]=sum[ls[x]],posm[x]=posm[ls[x]];
else sum[x]=sum[rs[x]],posm[x]=posm[rs[x]];
}
void update(int &x,int z,int add,int l,int r){
if(!x){
x=++cnt;
}
if(l==r){
sum[x]+=add;posm[x]=z/*z !l*/;
return;//void return sbsbsbsb
}
int mid=(l+r)>>;
if(z<=mid){
update(ls[x],z,add,l,mid);//
}
else update(rs[x],z,add,mid+,r);//递归儿子啊喂
pushup(x);
}
int merge(int x,int y,int l,int r){
if(!x||!y){
return x+y;
}
if(l==r){
sum[x]+=sum[y];
return x;
}
int mid=(l+r)>>;
ls[x]=merge(ls[x],ls[y],l,mid);
rs[x]=merge(rs[x],rs[y],mid+,r);
pushup(x);
return x;
}
void dfs(int x){
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(y==f[x][]) continue;
//root[x]=merge(root[x],root[y],ls[x],rs[x]); my wrong way
dfs(y);
root[x]=merge(root[x],root[y],,m);
}
if(sum[root[x]])ans[x]=num[posm[root[x]]];//num[posm[root[x]]] x wai yaojia root
}
int main(){
scanf("%d%d",&n,&m);
t=log2(n);
for(int i=;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
bfs();
for(int i=;i<=m;i++){
scanf("%d%d%d",&x[i],&yy[i],&zz[i]);
num[i]=zz[i];
}
sort(num+,num++m);
for(int i=;i<=m;i++){
zz[i]=lower_bound(num+,num+m/*m !n*/+,zz[i])-num;
int lca=Lca(x[i],yy[i]);
update(root[x[i]],zz[i],,,m);update(root[yy[i]],zz[i],,,m);update(root[lca],zz[i],-,,m);if(f[lca][])update(root[f[lca][]],zz[i],-,,m);
}
dfs();
for(int i=;i<=n;i++) printf("%d\n",ans[i]);
}

我还是太弱了,orzorz。

bzoj3307 雨天的尾巴题解及改题过程(线段树合并+lca+树上差分)的更多相关文章

  1. P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (树上差分+线段树合并)

    显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/st ...

  2. bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)

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

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

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

  4. bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】

    这居然是我第一次写线段树合并--所以我居然在合并的时候加点结果WAWAWAMLEMLEMLE--!ro的时候居然直接指到la就行-- 树上差分,每个点建一棵动态开点线段树,然后统计答案的时候合并即可 ...

  5. 【HNOI2012】永无乡 题解(并查集+线段树合并)

    题目链接 给定一张含$n$个点$m$条边的无向图,每个点有一个重要指数$a_i$.有两种操作:1.在$x$和$y$之间连一条边:2.求$x$所在连通块中重要程度第$k$小的点. ----------- ...

  6. 【BZOJ3307】雨天的尾巴 题解(树链剖分+树上差分)

    题目链接 题目大意:给定一颗含有$n$个结点的树,每次选择两个结点$x$和$y$,对从$x$到$y$的路径上发放一带$z$类型的物品.问完成所有操作后每个结点发放最多的时哪种物品. 普通的树链剖分貌似 ...

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

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

  8. [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)

    [BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...

  9. 雨天的尾巴(bzoj3307)(线段树合并+树上差分)

    \(N\)个点,形成一个树状结构.有\(M\)次发放,每次选择两个点\(x,y\) 对于\(x\)到\(y\)的路径上(含\(x,y\))每个点发一袋\(Z\)类型的物品.完成 所有发放后,每个点存放 ...

随机推荐

  1. DashBoard-身份验证

    dashboard1.7.1版本之后,新增了用户登录认证的功能. 默认dashboard会跳转到登录页面: 我们可以看到dashboard提供了Kubeconfig和token两种登录方式,我们可以直 ...

  2. 牛客 132C 简单瞎搞题 (bitset)

    大意: 给定序列$a$的第$i$个元素的取值范围$[L_i,R_i]$, 求$a$的平方和的种类数. 用bitset优化, 复杂度$O(\frac{n^5}{\omega})$ #include &l ...

  3. LeetCode面试常见100题( TOP 100 Liked Questions)

    LeetCode面试常见100题( TOP 100 Liked Questions) 置顶 2018年07月16日 11:25:22 lanyu_01 阅读数 9704更多 分类专栏: 面试编程题真题 ...

  4. Django: ORM 数据库设置和读写分离

    一.Django的数据库配置 (一)修改settings.py文件关于数据库的配置: Django默认使用sqlite: # Django默认的数据库库,SQLit配置 DATABASES = { ' ...

  5. 高并发之nginx限制

    Nginx限速模块分为哪几种?按请求速率限速的burst和nodelay参数是什么意思?漏桶算法和令牌桶算法究竟有什么不同?本文将带你一探究竟. 我们会通过一些简单的示例展示Nginx限速限流模块是如 ...

  6. js之数据类型(对象类型——构造器对象——对象)

    JavaScript中除了原始类型,null,undefined之外就是对象了,对象是属性的集合,每个属性都是由键值对(值可以是原始值,比如说是数字,字符串,也可以是对象)构成的.对象又可分为构造器对 ...

  7. axios跨域问题(包括开发环境和生产环境)

    之前写过一篇axios跨域问题,写的过于片面,没有考虑过实际开发中遇到的问题,以及如何全局使用axios,这次再写一篇,以后再有新发现再更新... 1.在static文件夹下新建/js/config. ...

  8. telnet命令测试端口连接是否正常, telnet不是内部或外部命令的方案

    telnet ip地址 端口 1.点击开始 → 运行 → 输入CMD,回车.2.在DOS界面里,输入telnet测试端口命令:   telnet IP 端口  或  telnet 域名 端口,回车. ...

  9. 热门前沿知识相关面试问题-android插件化面试问题讲解

    插件化由来: 65536/64K[技术层面上]随着代码越来越大,业务逻辑越来繁杂,所以很容易达到一个65536的天花板,其65536指的是整个项目中的方法总数如果达到这个数量时则不无法创建新的方法了, ...

  10. BZOJ 1003 最短路dp

    物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪.由于各种因 ...