P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并
[Vani有约会] 雨天的尾巴 /【模板】线段树合并
题目背景
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。
题目描述
首先村落里的一共有 座房屋,并形成一个树状结构。然后救济粮分 次发放,每次选择两个房屋 ,然后对于 到 的路径上(含 和 )每座房子里发放一袋 类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。
输入格式
输入的第一行是两个用空格隔开的正整数,分别代表房屋的个数 和救济粮发放的次数 。
第 到 第 行,每行有两个用空格隔开的整数 ,代表存在一条连接房屋 和 的边。
第 到第 行,每行有三个用空格隔开的整数 ,代表一次救济粮的发放是从 到 路径上的每栋房子发放了一袋 类型的救济粮。
输出格式
输出 行,每行一个整数,第 行的整数代表 号房屋存放最多的救济粮的种类,如果有多种救济粮都是存放最多的,输出种类编号最小的一种。
如果某座房屋没有救济粮,则输出 。
样例 #1
样例输入 #1
5 3 1 2 3 1 3 4 5 3 2 3 3 1 5 2 3 3 3
样例输出 #1
2 3 3 0 2
提示
- 对于 的数据,保证 。
- 对于 的数据,保证 。
- 对于 测试数据,保证 ,,。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+100,INF=1e5; struct segtree { int val,lc,rc,num; }s[N<<7]; vector<int >to[N]; int n,m,root[N],deg[N],tot,ans[N]; int dep[N],f[N],siz[N],son[N],top[N]; void go1(int u,int fa) { f[u]=fa; siz[u]=1; dep[u]=dep[fa]+1; for(int i=0;i<deg[u];++i) { int v=to[u][i]; if(v==fa) continue; go1(v,u); siz[u]+=siz[v]; if(siz [ son[u] ] < siz[v]) son[u]=v; } } void go2(int u,int tp) { top[u]=tp; if(son[u]) go2(son[u],tp); for(int i=0;i<deg[u];++i) { int v=to[u][i]; if(v==son[u] || dep[v]<dep[u]) continue; go2(v,v); } } int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); x=f[top[x]]; } if(dep[x]<dep[y]) swap(x,y); return y; } void pushup(segtree &nw,segtree &lc,segtree &rc) { nw.val=lc.val+rc.val; nw.num=max(lc.num,rc.num); } void upd(int &i,int l,int r,int x,int z) { if(i==0) i=++tot; if(l==r) { s[i].val+=z; s[i].num=s[i].val; return ; } int mid=(l+r)>>1; if(x<=mid) upd(s[i].lc,l,mid,x,z); else upd(s[i].rc,mid+1,r,x,z); pushup(s[i],s[s[i].lc],s[s[i].rc]); } int que(int i,int l,int r) { if(l==r) return l; int mid=(l+r)>>1,num=0; if(s[ s[i].lc ].num>=s[ s[i].rc ].num) num=que(s[i].lc,l,mid); else num=que(s[i].rc,mid+1,r); return num; } void merg(int &i,int &j,int l,int r)//i <-- j { if(i==0 || j==0) { i+=j; return ; } if(l==r) { s[i].val+=s[j].val; s[i].num=s[i].val; return ; } int mid=(l+r)>>1; merg(s[i].lc,s[j].lc,l,mid); merg(s[i].rc,s[j].rc,mid+1,r); pushup(s[i], s[s[i].lc] , s[s[i].rc]); } void gotans(int u); void init() { scanf("%d%d",&n,&m); for(int i=1,x,y;i<n;++i) { scanf("%d%d",&x,&y); ++deg[x]; ++deg[y]; to[x].push_back(y); to[y].push_back(x); } go1(1,0); go2(1,1); } void work() { for(int i=1,x,y,z;i<=m;++i) { scanf("%d%d%d",&x,&y,&z); int ace=lca(x,y); upd(root[x],1,INF,z,1); upd(root[y],1,INF,z,1); upd(root[ace],1,INF,z,-1); if(f[ace]>0) upd(root[f[ace]],1,INF,z,-1); } gotans(1); for(int i=1;i<=n;++i) printf("%d\n",ans[i]); } void gotans(int u) { for(int i=0,v;i<deg[u];++i) { v=to[u][i]; if(dep[v]<dep[u]) continue; gotans(v); merg(root[u],root[v],1,INF); } if(root[u]>0) ans[u]=que(root[u],1,INF); } int main() { init(); work(); return 0; } https://www.luogu.com.cn/problem/P3224
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18617814
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程