题面:https://www.luogu.com.cn/problem/P4556

对于在一条(x,y)路径上将z加1。

就可以树上差分。

x和y都是加1。lca是减1,lca的father也是减1。

但是由于又有很多种不一样的种类。

还需要每个点维护一个线段树。

合并的时候求哪个种类是max。

最后统计答案dfs。

思路简单,主要是代码长。

代码如下:

#pragma-GCC-optimize("O2,Ofast,inline,unroll-all-loops,-ffast-math")
#pragma-GCC-target("avx,sse2,sse3,sse4,popcnt")
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int tt,n,m;
struct node{int nxt,to;#define nxt(x) e[x].nxt#define to(x) e[x].to
}e[maxn<<1];
int head[maxn],tot,dep[maxn],f[maxn][21],rt[maxn],num,cnt,X[maxn],Y[maxn],Z[maxn],val[maxn],ans[maxn];
inline void add(int x,int y){to(++tot)=y;nxt(tot)=head[x];head[x]=tot;
}
queue<int> q;
inline long read(){long x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-')f*=-1;c=getchar();}while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x*f;
}
inline void bfs(){q.push(1);dep[1]=1;while(q.size()){int x=q.front();q.pop();for(int i=head[x];i;i=nxt(i)){int to=to(i);if(dep[to]) continue;dep[to]=dep[x]+1;f[to][0]=x;for(int j=1;j<=tt;j++)f[to][j]=f[f[to][j-1]][j-1];q.push(to);}}
}
inline int lca(int x,int y){if(dep[x]>dep[y]) swap(x,y);for(int i=tt;i>=0;i--)if(dep[f[y][i]] >= dep[x]) y=f[y][i];if(x==y) return x;for(int i=tt;i>=0;i--)if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];return f[x][0];
}
struct tree{int lc,rc,dt,tg;
}t[maxn*80];
void insert(int p,int l,int r,int vl,int d){if(l==r){t[p].dt+=d;t[p].tg=t[p].dt ? l : 0 ;return;}int mid=(l+r)>>1;if(vl<=mid){if(!t[p].lc) t[p].lc=++num;insert(t[p].lc,l,mid,vl,d);}else{if(!t[p].rc) t[p].rc=++num;insert(t[p].rc,mid+1,r,vl,d);}t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt);t[p].tg=t[t[p].lc].dt>=t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg;
}
int merge(int p,int q,int l,int r){if(!p) return q;if(!q) return p;if(l==r){t[p].dt+=t[q].dt;t[p].tg=t[p].dt ? l : 0;return p;}int mid=(l+r)>>1;t[p].lc=merge(t[p].lc,t[q].lc,l,mid);t[p].rc=merge(t[p].rc,t[q].rc,mid+1,r);t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt);t[p].tg=t[t[p].lc].dt>=t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg;return p;
}
void dfs(int x){for(int i=head[x];i;i=nxt(i)){int to=to(i);if(dep[to]<=dep[x]) continue;dfs(to);rt[x]=merge(rt[x],rt[to],1,cnt);}ans[x]=t[rt[x]].tg;
}
int main()
{n=read(),m=read();tt=(int)(log(n)/log(2))+1;for(int i=1;i<n;i++){int x,y;x=read();y=read();add(x,y);add(y,x);}bfs();for(int i=1;i<=n;i++) rt[i]=++num;for(int i=1;i<=m;i++){X[i]=read();Y[i]=read();Z[i]=read();val[i]=Z[i];}sort(val+1,val+1+m);cnt=unique(val+1,val+1+m)-val-1;for(int i=1;i<=m;i++){int x=X[i],y=Y[i];int z=lower_bound(val+1,val+1+cnt,Z[i])-val;int lc=lca(x,y);insert(rt[x],1,cnt,z,1);insert(rt[y],1,cnt,z,1);insert(rt[lc],1,cnt,z,-1);if(f[lc][0]) insert(rt[f[lc][0]],1,cnt,z,-1);}dfs(1);for(int i=1;i<=n;i++) printf("%d\n",val[ans[i]]);return 0;
}

转载于:https://www.cnblogs.com/ChrisKKK/p/11544029.html

Luogu_P4556 雨天的尾巴【题解】树上差分 线段树合并相关推荐

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

    题目链接 解题思路: 首先题目是对u,vu,vu,v这两条路径上面添加一个zzz,然后运用树上点的差分思想,对于分发路径u,vu,vu,v,我们在uuu上+1+1+1,在vvv上+1+1+1,在lca ...

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

    题目链接:点击查看 题目大意:给出一棵树,再给出 m 次操作,每次操作会选择两个点 ( x , y ) ,使得这条路径上的所有点的种类 z 加一,最后问每个点的哪个种类出现的频率最高,若多个种类出现频 ...

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

    题目链接 Solution 树上差分+线段树合并. 在每个节点上维护一棵权值线段树. 然后如果需要修改 \(x,y\) 两点,则在 \(x\) 处和 \(y\) 处分别加上 \(1\) 的权值. 然后 ...

  4. YbtOJ#532-往事之树【广义SAM,线段树合并】

    正题 题目链接:https://www.ybtoj.com.cn/problem/532 题目大意 给出nnn个点的一个TrieTrieTrie树,定义SxS_xSx​表示节点xxx代表的字符串 求m ...

  5. BZOJ5419[Noi2018]情报中心——线段树合并+虚树+树形DP

    题目链接: [NOI2018]情报中心 题目大意:给出一棵n个节点的树,边有非负边权,并给出m条链,对于每条链有一个代价,要求选出两条有公共边的链使两条链的并的边权和-两条链的代价和最大. 花了一天的 ...

  6. 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解

    题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...

  7. 雨中的尾巴(线段树合并+树上差分)

    哇这道题 恶心死我 首先要知道,树上差分一般解决的问题是关于树上的覆盖问题 然后遇到覆盖问题尽量不要打树剖(会慢很多) 关于此题 因为这道题覆盖的是 从xxx到yyy的点 所以我们在 x,yx,yx, ...

  8. [NOIP2016]天天爱跑步 题解(树上差分) (码长短跑的快)

    Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图 ...

  9. 【NOIP2016】【桶/线段树合并】【树上差分】天天爱跑步

    [题目描述] [思路] 这是道好题呀.考虑把一条路径(u,v)拆成两条:从u到lca(u,v),从lca(u,v)到v.下面我们以向上的路径为例讨论做法.对于一条向上的路径,它对一个点x有贡献当且仅当 ...

  10. 线段树合并与分裂维护树上最长上升子序列 + 点分治删点 ---- 2021 牛客多校第一场 C - Cut the tree(详解)

    题目大意: 给你一个树,树上每个点都有一个权值valnodeval_{node}valnode​,路径(u,v)(u,v)(u,v) 上所有点按顺序有序序列,令f(u,v)f(u,v)f(u,v)是这 ...

最新文章

  1. Python程序设计题解【蓝桥杯官网题库】 DAY7-基础练习
  2. python编程语言是什么-python是什么编程语言
  3. laravel 队列queue
  4. android数据存放map_android - Java后台把数据用json发到手机端,里面是map存放的,必须要说明数据的类型?...
  5. PHP 接口输出 图片
  6. js 实现 复制 功能 (zeroclipboard)
  7. jvm系列(九):如何优化Java GC
  8. oracle dba_waiters中的lockid是什么,查杀oracle lock session and table
  9. Web端H.265播放器研发解密
  10. 戴尔计算机软件的安装,买的新戴尔电脑怎么安装软件
  11. 数学建模十大常用软件(转)
  12. 未来时速——第一章 用事实的力量管理企业
  13. 我的创作纪念日 | 软件测试成长之路
  14. 解决......lib/include/THC/THCGeneral.h:12:18: fatal error: cuda.h: No such file or directory报错问题
  15. 利用泰勒展开式实现sin(x),cos(x)函数
  16. linux otl mysql_Linux下用OTL操作MySql(包含自己封装的类库及演示样例代码下载)...
  17. 如何使用ChatGPT做一份五一出游攻略?
  18. Neuronal Dynamics:Hodgkin-Huxley model 实验结果展示
  19. Android可拖动可吸附悬浮窗
  20. 【2020算法练习一】笔试选择题 快手2020校园招聘秋招笔试--算法A试卷

热门文章

  1. 智能家居APP使用指南
  2. 逆流而上,整合阿里高频考点2023Java岗面试突击指南手册最新首发
  3. 使用redis缓存技术实现省市区三级联动
  4. Java操作Oracle数据库——ARRAY TABLE类型批量数据处理区别比较
  5. Access denied for user ‘bijian0530‘@‘localhost‘ (using password: YES)
  6. 波段高低点指标公式 k线高低点 大盘主图公式源码
  7. 本地打印后台处理程序服务没有运行和windows无法连接到打印机拒绝访问
  8. 电脑没有长截图功能,一招即可截下来!如何用电脑做长截图
  9. 三、Logstash安装部署
  10. 响应式H5图片网盘外链系统源码 自适应PC手机端