链接

点击跳转

题解

树差分,合并权值线段树

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define maxe 200010
#define maxk 17
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{ll c, f(1);for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;for(;isdigit(c);c=getchar())x=x*10+c-0x30;return f*x;
}
struct joinable_segment_tree
{int sum[maxn*18*4], mx[maxn*18*4], ch[maxn*18*4][2], tot;void clear(){tot=0;}int New(int v=0){tot++;sum[tot]=v, mx[tot]=v;ch[tot][0]=ch[tot][1]=0;return tot;}int create(int l, int r, int pos, int v)  //创建一条链{int ret=New(v), o=ret;while(l<r){int mid(l+r>>1);if(pos<=mid)o=ch[o][0]=New(v), r=mid;else o=ch[o][1]=New(v), l=mid+1;}return ret;}void upd(int o){sum[o]=sum[ch[o][0]]+sum[ch[o][1]];mx[o]=max(mx[ch[o][0]],mx[ch[o][1]]);}int join(int u, int v, int _l, int _r){if(!u or !v)return u|v;if(_l==_r){sum[u]+=sum[v];mx[u]=sum[u];return u;}int mid(_l+_r>>1);ch[u][0]=join(ch[u][0],ch[v][0],_l,mid);ch[u][1]=join(ch[u][1],ch[v][1],mid+1,_r);upd(u);return u;}int qsum(int o, int l, int r, int _l, int _r){int mid(_l+_r>>1), ans(0);if(l<=_l and r>=_r)return sum[o];if(l<=mid)ans+=qsum(ch[o][0],l,r,_l,mid);if(r>mid)ans+=qsum(ch[o][1],l,r,mid+1,_r);return ans;}int qmax(int o, int l, int r, int _l, int _r){int mid(_l+_r>>1), ans(-iinf);if(l<=_l and r>=_r)return mx[o];if(l<=mid)ans=max(ans,qmax(ch[o][0],l,r,_l,mid));if(r>mid)ans=max(ans,qmax(ch[o][1],l,r,mid+1,_r));return ans;}
}mori;
struct Graph
{int etot, head[maxn], to[maxe], next[maxe], w[maxe];void clear(int N){for(int i=1;i<=N;i++)head[i]=0;etot=0;}void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}#define forp(pos,G) for(auto p=G.head[pos];p;p=G.next[p])
}G;
struct Doubling_LCA
{int f[maxn][maxk+1], depth[maxn];void clear(int n){for(int i=1;i<=n;i++)depth[i]=0, cl(f[i]);}void dfs(Graph &G, int pos, int pre){for(auto k=1;(1<<k)<=depth[pos];k++)f[pos][k]=f[f[pos][k-1]][k-1];for(auto p(G.head[pos]);p;p=G.next[p])if(G.to[p]!=pre){f[G.to[p]][0]=pos;depth[G.to[p]]=depth[pos]+1;dfs(G,G.to[p],pos);}}void run(Graph &G, int root){depth[root]=1;dfs(G,root,0);}int q(int x, int y){if(depth[x]<depth[y])swap(x,y);for(auto k(maxk);~k;k--)if(depth[f[x][k]]>=depth[y])x=f[x][k];if(x==y)return x;for(auto k(maxk);~k;k--)if(f[x][k]!=f[y][k])x=f[x][k], y=f[y][k];return f[x][0];}int jp(int x, int b){for(auto k=0;k<=maxk;k++)if(b&(1<<k))x=f[x][k];return x;}
}db;
int n, m, rt[maxn], ans[maxn];
void add(int u, int z, int v)
{int r=mori.create(1,1e5,z,v);rt[u]=mori.join(rt[u],r,1,1e5);
}
int q(int o, int _l, int _r)
{if(_l==_r)return _l;int mx=mori.mx[o], mxl=mori.mx[mori.ch[o][0]], mxr=mori.mx[mori.ch[o][1]], mid(_l+_r>>1);if(mx==mxl)return q(mori.ch[o][0],_l,mid);else return q(mori.ch[o][1],mid+1,_r);
}
void dfs(int pos, int pre)
{forp(pos,G)if(G.to[p]!=pre){auto v=G.to[p];dfs(v,pos);rt[pos]=mori.join(rt[pos],rt[v],1,1e5);}if(mori.mx[rt[pos]]>0)ans[pos]=q(rt[pos],1,1e5);
}
int main()
{int n=read(), m=read(), i, u, v, z;rep(i,n-1){u=read(), v=read();G.adde(u,v), G.adde(v,u);}db.run(G,1);rep(i,m){u=read(), v=read(), z=read();int lca=db.q(u,v);add(u,z,+1);add(v,z,+1);add(lca,z,-1);if(lca>1)add(db.f[lca][0],z,-1);}dfs(1,0);rep(i,n)printf("%d\n",ans[i]);return 0;
}

洛谷P4556 [Vani有约会]雨天的尾巴相关推荐

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

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

  2. 洛咕 P4556 [Vani有约会]雨天的尾巴

    终于把考试题清完了...又复活了... 树上差分,合并用线段树合并,但是空间会炸. 某大佬:lca和fa[lca]减得时候一定已经存在这个节点了,所以放进vector里,合并完之后减掉就好了... 玄 ...

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

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

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

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

  5. 数论:扩展欧几里德(洛谷P1516 青蛙的约会)

    欧几里德 基本思想:gcd(q,r)=gcd(r,q%r); 证明,设q.r的最大公因数为a,则q=xa,r=ya,xy互质 不妨设x>y(显然如果小于会在一次gcd运算后交换) 则q%r=(x ...

  6. 洛谷 P1516 青蛙的约会

    https://www.luogu.org/problemnew/show/P1516#sub 题意还是非常好理解的..... 假如这不是一道环形的跑道而是一条直线,你会怎样做呢? 如果是我就会列一个 ...

  7. 烦神的斐波那契洛谷-1306-斐波那契公约数

    传送门 洛谷1306传送门 -------------------------------------------------------------------------------------- ...

  8. 二分答案——烦恼的高考志愿(洛谷 P1678)

    题目选自洛谷P1678 如果仅仅是套循环的话显然在数据比较大的情况下是不够优化 的,所以我们可以先把得到的分数线排序再二分操作. 这道题二分的原理很简单,因为我们求的是某一个学生和某一个分数线最小的差 ...

  9. P8318 『JROI-4』淘气的猴子(【LGR-108】洛谷 5 月月赛 I JROI R4 Div.2)

    众所周知,jockbutt 是一个可爱的女孩纸. 题目描述 jockbutt 有一个正整数序列,长度为 n,分别为 a1,a2...an,她非常喜欢这个序列,平时都非常爱惜它们. 可是有一天,当 jo ...

  10. 洛谷.P1678 烦恼的高考志愿

    链接: P1678 烦恼的高考志愿 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目: 计算机竞赛小组的神牛 V 神终于结束了高考,然而作为班长的他还不能闲下来,班主任老 t 给 ...

最新文章

  1. (0050)iOS开发之钥匙串存储
  2. python趣味编程10例-达人迷 Python趣味编程10例
  3. python No-ASCII character ,编码错误
  4. C/C++ 中指针和引用的区别
  5. Android 底部上拉抽屉view
  6. CSS3 控制Tab宽度 tab-size属性
  7. ecshop备份数据 ecshop转移数据 ecshop更换主机
  8. android 模拟器 3D 开发环境配置
  9. jdk 安装cmd运行java_windows下安装jdk,cmd下编译运行java程序一点心得
  10. 现场活动画面组织控制及抽奖的使用疑难问题汇编
  11. 综合布线(楼栋)设计报告
  12. 华为认证数通HCIE面试之Qos完整解析
  13. 华为笔记本没有HOME键和END键
  14. monetDb列式存储架构分析
  15. Python: 傅里叶级数
  16. css 背景渐变 图像_交叉渐变背景图像
  17. oracle form on query,OracleForm实战总结.doc
  18. VS Studio和VS Code,IntelliJ IDEA的护眼背景色设置
  19. 微软今天发布的紧急安全公告 MS08-067
  20. 华为少帅李一男是如何沦陷的【附任正非讲话】

热门文章

  1. 苹果电脑怎么清理垃圾和缓存文件,mac如何清理系统缓存文件
  2. 火狐浏览器的css写法,CSS样式IE浏览器跟火狐浏览器兼容写法
  3. 54_集合类库(上)
  4. 乔布斯:这九本书每个人都该读一读
  5. CSS 固定定位 position fixed
  6. 完全平方数的几种判定方法与算法用时
  7. 耐得住寂寞,拥得了繁华
  8. MySQL常用的关键字查询用法
  9. 问题解决_系统识别不了内存
  10. 中望3d快捷键命令大全_中望CAD快捷键汇总