虽然是个板子,但用到了差分思想。

Description

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

Solution

离线记录所有操作后把物品编号离散化,

之后修改路径信息时用到了点差分的思想。在线段树中记录差分数据,最后由叶节点开始合并,通过子树求和算出该点实际数据。

每次更改时只在两端点处加1,在lca处减1,再在lca父亲处减1即可。应该很好理解。

另外,应用边差分时,要现将边权化为点权,之后在两端点处加,在lca处减,无需更改lca父亲。(虽然这题没用到

具体看代码实现:

  1 #include<bits/stdc++.h>
2 #define debug cout<<"wrong"<<endl
3 using namespace std;
4 const int NN=1e5+5;
5 int n,m,to[NN<<1],nex[NN<<1],head[NN],num,x[NN],y[NN],z[NN],ans[NN];
6 int dep[NN],f[NN][60],tmp[NN],ext,logg,rt[NN];
7 inline int read(){
8 int x=0,f=1;
9 char ch=getchar();
10 while(ch<'0'||ch>'9'){
11 if(ch=='-') f=-1;
12 ch=getchar();
13 }
14 while(ch>='0'&&ch<='9'){
15 x=(x<<1)+(x<<3)+(ch^48);
16 ch=getchar();
17 }
18 return x*f;
19 }
20 inline void add(int a,int b){
21 to[++num]=b; nex[num]=head[a]; head[a]=num;
22 to[++num]=a; nex[num]=head[b]; head[b]=num;
23 }
24 inline int lca(int a,int b){
25 if(dep[a]>dep[b]) swap(a,b);
26 for(int i=logg;i>=0;i--)
27 if(dep[f[b][i]]>=dep[a]) b=f[b][i];
28 if(a==b) return a;
29 for(int i=logg;i>=0;i--)
30 if(f[a][i]!=f[b][i]) a=f[a][i], b=f[b][i];
31 return f[a][0];
32 }
33 void write(int x){
34 if(x<0) putchar('-'), x=-x;
35 if(x>9) write(x/10);
36 putchar(x%10+'0');
37 }
38 void init(){
39 n=read(); m=read();
40 for(int i=1;i<n;i++) add(read(),read());
41 for(int i=1;i<=m;i++) x[i]=read(), y[i]=read(), tmp[i]=z[i]=read();
42
43 sort(tmp+1,tmp+1+m);
44 ext=unique(tmp+1,tmp+1+m)-tmp-1;
45 for(int i=1;i<=m;i++) z[i]=lower_bound(tmp+1,tmp+ext+1,z[i])-tmp;
46
47 queue<int> q;
48 dep[1]=1; logg=log2(n)+1; q.push(1);
49 while(!q.empty()){
50 int a=q.front(); q.pop();
51 for(int i=head[a];i;i=nex[i]){
52 int b=to[i];
53 if(dep[b]) continue;
54 dep[b]=dep[a]+1; f[b][0]=a;
55 for(int j=1;j<=logg;j++) f[b][j]=f[f[b][j-1]][j-1];
56 q.push(b);
57 }
58 }
59 }
60 struct node{
61 int seg,ls[NN*60],rs[NN*60],typ[NN*60],sum[NN*60];
62 void pushup(int x){
63 if(sum[ls[x]]>=sum[rs[x]]) sum[x]=sum[ls[x]], typ[x]=typ[ls[x]];
64 else sum[x]=sum[rs[x]], typ[x]=typ[rs[x]];
65 }
66 void insert(int &x,int l,int r,int pos,int v){
67 if(!x) x=++seg;
68 if(l==r){
69 typ[x]=pos;
70 sum[x]+=v;
71 return;
72 }
73 int mid=(l+r)>>1;
74 if(pos<=mid) insert(ls[x],l,mid,pos,v);
75 else insert(rs[x],mid+1,r,pos,v);
76 pushup(x);
77 }
78 void marge(int &x,int y,int l,int r){
79 if(!x||!y){ x=x+y; return; }
80 if(l==r){ sum[x]+=sum[y]; typ[x]=l; return; }
81 int mid=(l+r)>>1;
82 marge(ls[x],ls[y],l,mid);
83 marge(rs[x],rs[y],mid+1,r);
84 pushup(x);
85 }
86 }segt;
87 void dfs(int fa,int st){
88 for(int i=head[st];i;i=nex[i]){
89 int t=to[i];
90 if(t==fa) continue;
91 dfs(st,t);
92 segt.marge(rt[st],rt[t],1,ext);
93 }
94 if(segt.sum[rt[st]]) ans[st]=tmp[segt.typ[rt[st]]];
95 }
96 int main(){
97 init();
98 for(int i=1;i<=m;i++){
99 int ca=lca(x[i],y[i]);
100 segt.insert(rt[x[i]],1,ext,z[i],1);
101 segt.insert(rt[y[i]],1,ext,z[i],1);
102 segt.insert(rt[ca],1,ext,z[i],-1);
103 if(f[ca][0]) segt.insert(rt[f[ca][0]],1,ext,z[i],-1);
104 }
105 dfs(0,1);
106 for(int i=1;i<=n;i++)
107 write(ans[i]), putchar('\n');
108 return 0;
109 }

最新文章

  1. Lua pureMVC
  2. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 防止暴力破解密码、提高大型信息系统安全
  3. Abp公共连接和事务管理方法
  4. java中set接口的用法
  5. 使用WebApi时Post和Put的区别
  6. Java 10大精华文章收集001
  7. WordPress折腾日记
  8. CGAffineTransform与CATransform3D
  9. Red Gate Software 软件推荐
  10. char,wchar_t,WCHAR,TCHAR,ACHAR的区别----LPCTSTR
  11. Asp.Net验证码3
  12. iOS开发网络篇--NSURLConnection
  13. Jquery中$.post()与$.get()区别
  14. Toolkit Pro学习--Toolbar的创建
  15. SharePoint 2010 -- Silverlight托管客户端模型简单示例
  16. pytorch中tensorboardX的用法
  17. PolarCode
  18. Redis学习系列六ZSet(有序列表)及Redis数据结构的过期
  19. 使用xunit对asp.net core webapi进行集成测试
  20. &lt;数据挖掘导论&gt;读书笔记5关联分析的基本概念和算法

热门文章

  1. Identity用户管理入门四(修改、删除用户)
  2. Object类、Date类、Calendar类、System类、StringBuilder类和基本类型包装类
  3. 使用easyui进行上左右布局
  4. c# 扩展方法奇思妙用基础篇九:Expression 扩展
  5. c++ if语句讲解&amp;例题
  6. 解决IE浏览器 点击子元素重复调用执行 mouseover 与mouseout兼容性问题
  7. ecshop二次开发秒杀、限时折扣、清仓等功能
  8. openFeign夺命连环9问,这谁受得了?
  9. requests访问页面时set-cookie获取cookie
  10. 计算机python二级 第六套