题目链接:点击查看

题目大意:给出一棵树,再给出 m 次操作,每次操作会选择两个点 ( x , y ) ,使得这条路径上的所有点的种类 z 加一,最后问每个点的哪个种类出现的频率最高,若多个种类出现频率相同时,输出编号最小的

题目分析:线段树合并模板题,感觉 update 函数和主席树非常像,所以就仿照主席树的写法去实现的,相比于正常的线段树来说,仅仅多了一个 merge 函数用于合并两棵线段树罢了,时间复杂度是严格 nlogn 的,因为维护的时候采用的是树上差分,即:

  1. x + 1
  2. y + 1
  3. lca( x , y ) - 1
  4. fa[ lca( x , y ) ] -1

对于某次操作共需要维护 4 条链,也就是说总共需要维护 4 * m * logn 条链,所以空间需要开 50 倍才够,对于这个题目而言,在每个节点上都维护一棵线段树然后 dfs 合并即可

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;vector<int>node[N];int ans[N];int dp[N][20],deep[N];void dfs(int u,int fa,int dep)
{deep[u]=dep;dp[u][0]=fa;for(int i=1;i<20;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(auto v:node[u]){if(v==fa)continue;dfs(v,u,dep+1);}
}int LCA(int x,int y)
{if(deep[x]<deep[y])swap(x,y);for(int i=19;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=19;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0];
}struct Node
{int l,r,mmax,id;
}tree[N*50];int root[N],tot;void pushup(int k)
{if(tree[tree[k].l].mmax>=tree[tree[k].r].mmax){tree[k].mmax=tree[tree[k].l].mmax;tree[k].id=tree[tree[k].l].id;}else{tree[k].mmax=tree[tree[k].r].mmax;tree[k].id=tree[tree[k].r].id;}
}void update(int& k,int pos,int val,int l,int r)
{if(!k)k=++tot;assert(tot<N*50);if(l==r){tree[k].mmax+=val;tree[k].id=l;return;}int mid=l+r>>1;if(pos<=mid)update(tree[k].l,pos,val,l,mid);elseupdate(tree[k].r,pos,val,mid+1,r);pushup(k);
}void merge(int& a,int b,int l,int r)
{if(!a||!b){a=a+b;return;}if(l==r){tree[a].mmax+=tree[b].mmax;tree[a].id=l;return;}int mid=l+r>>1;merge(tree[a].l,tree[b].l,l,mid);merge(tree[a].r,tree[b].r,mid+1,r);pushup(a);
}void dfs_ans(int u,int fa)
{for(auto v:node[u]){if(v==fa)continue;dfs_ans(v,u);merge(root[u],root[v],1,100000);}if(tree[root[u]].mmax)ans[u]=tree[root[u]].id;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs(1,0,0);while(m--){int x,y,z;scanf("%d%d%d",&x,&y,&z);int lca=LCA(x,y); update(root[x],z,1,1,100000);update(root[y],z,1,1,100000);update(root[lca],z,-1,1,100000);update(root[dp[lca][0]],z,-1,1,100000);}dfs_ans(1,0);for(int i=1;i<=n;i++)printf("%d\n",ans[i]);return 0;
}

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

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

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

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

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

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

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

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

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

  5. 洛谷 P1516 青蛙的约会

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

  6. 洛谷 - P4390 [BOI2007]Mokia 摩基亚(带修二维数点-四叉线段树/CDQ分治)

    题目链接:点击查看 题目大意:给出一个二维平面坐标系,需要执行数次操作,具体操作分为下列两种: 1 x y a:坐标 (x,y)(x,y)(x,y) 加上 aaa 个点 2 x1 y1 x2 y2:查 ...

  7. 【洛谷 P2633】 Count on a tree(主席树,树上差分)

    题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...

  8. 洛谷P1536村村通(并查集模板题)

    问题出处: https://www.luogu.com.cn/problem/P1536 题目描述: 某市调查城镇交通状况,得到现有城镇道路统计表.表中列出了每条道路直接连通的城镇.市政府 " ...

  9. 并查集——集合(洛谷 P1621)

    题目选自洛谷P1621 一道并查集类型的算法题,基本框架不变,就是合并的时候怎么合并,合并哪些数? 筛出素数之后找出在 'p~b' 范围内的素数 然后枚举a~b之间的数,合并他们 最后看看那些数的祖先 ...

最新文章

  1. 还在用Swagger生成接口文档?我推荐你试试它.....
  2. 全球与中国抗生素软膏市场运营现状十四五及前景规划分析报告2021-2027年版
  3. 2层框架结构柱子间距_框架结构的特点有哪些?框架结构是什么?
  4. 对lua协程的一点理解
  5. Android中的广播Broadcast详解
  6. codevs4343 找回密码
  7. rust腐竹是什么意思_学习Rust 集合与字符串
  8. 怎么安装ABBYY FineReader
  9. 连接oracle数据库代码,oracle数据库的连接代码
  10. 【论文】本体匹配实体对齐知识融合入门论文推荐
  11. File Manager所支持的文件
  12. 根据输入的银行卡号识别出银行名称并显示
  13. c语言编译bss和data,认识bss段和data段
  14. 笔记:《高效能人士的七个习惯》第五章 习惯三 要事第一——自我管理的原则
  15. Ubuntu交叉编译U-boot
  16. 读《不要等到毕业以后》后感
  17. PMP之项目采购管理
  18. Java实现 LeetCode 321 拼接最大数
  19. QT 代码行统计工具
  20. python验证手机号是否注册学信网

热门文章

  1. rhel6.2安装oracle11g,RHEL 6.2 x86_64 下安装Oracle 11g步骤
  2. java jtable应用源码_JTable的应用(一)
  3. 个性化 服务器运行失败,VirtualBox 运行失败
  4. python中使用函数的优点,对于python类使用“get函数”有什么好处?
  5. EventLoopGroup 的实例化
  6. 策略模式Strategy Pattern应用场景
  7. 字符缓冲流特有功能复制Java文件
  8. Hive的基本操作-创建表的格式
  9. 数据库设计:pd工程创建数据库表
  10. notepad++ 远程连接阿里云服务器