权值线段树-动态开点-合并(P4556 [Vani有约会]雨天的尾巴

Posted --hpy-7m

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了权值线段树-动态开点-合并(P4556 [Vani有约会]雨天的尾巴相关的知识,希望对你有一定的参考价值。

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

树链加数,问你每个节点最多的是哪个数。

思路:

树链加数很容易想到差分。

从下往上用权值线段树合并即可,直接用pushup把答案存在树根即可,不用每次查询最多的数

  1 struct EDGE
  2 {
  3     int to,next;
  4 }edge[N];
  5 int tot;
  6 int head[N];
  7 void Init(int n)
  8 {
  9     tot=0;
 10     for(int i=0;i<=n;++i)
 11         head[i]=0;
 12 }
 13 void add(int from,int to)
 14 {
 15     ++tot;
 16     edge[tot].to=to;
 17     edge[tot].next=head[from];
 18     head[from]=tot;
 19 }//for(int i=head[x];i;i=edge[i].next)
 20 
 21 int f[N][25],d[N];
 22 void update(int x) {//用之前记得设f[x][0]
 23     for (int i=1; i<=24; i++)
 24         f[x][i]=f[f[x][i-1]][i-1];
 25     return ;
 26 }
 27 int LCA(int a, int b) {
 28     if (d[a]>d[b]) swap(a, b);
 29     int h=d[b]-d[a];
 30     for (int i=0; (1<<i)<=h; i++)
 31         if ((1<<i)&h) b=f[b][i];
 32     if (a!=b) {
 33         for (int i=24; i>=0; i--)
 34             if (f[a][i]!=f[b][i]) a=f[a][i], b=f[b][i];
 35         a=f[a][0];
 36     }
 37     return a;
 38 }
 39 void dfs1(int u,int fa){
 40     f[u][0]=fa;
 41     d[u]=d[fa]+1;
 42     update(u);
 43     for(int i=head[u];i;i=edge[i].next)
 44     {
 45         int to=edge[i].to;
 46         if(to==fa)continue;
 47         dfs1(to,u);
 48     }
 49 }
 50 
 51 int top;
 52 struct node
 53 {
 54     int sz,ans,lson,rson;
 55 }tr[N];
 56 int rt[N],R=100005;
 57 int res[N];
 58 void up(int x){
 59     if(tr[tr[x].lson].sz>=tr[tr[x].rson].sz)tr[x].ans=tr[tr[x].lson].ans,tr[x].sz=tr[tr[x].lson].sz;
 60     else tr[x].ans=tr[tr[x].rson].ans,tr[x].sz=tr[tr[x].rson].sz;
 61 }
 62 void insert(int &x,int l,int r,int pos,int val)
 63 {
 64     if(!x)x=++top,tr[top]=node();
 65     if(l==r){
 66         tr[x].sz+=val;
 67         tr[x].ans=l;
 68         return;
 69     }
 70     int mid=l+r>>1;
 71     if(pos<=mid)insert(tr[x].lson,l,mid,pos,val);
 72     else insert(tr[x].rson,mid+1,r,pos,val);
 73     up(x);
 74 }
 75 int n,m;
 76 int merge(int x,int y,int l,int r)
 77 {
 78     if(!x||!y)return x+y;
 79     if(l==r){
 80         tr[x].sz+=tr[y].sz;
 81         return x;
 82     }
 83     int mid=l+r>>1;
 84     tr[x].lson=merge(tr[x].lson,tr[y].lson,l,mid);
 85     tr[x].rson=merge(tr[x].rson,tr[y].rson,mid+1,r);
 86     up(x);
 87     return x;
 88 }
 89 void dfs(int u,int fa)
 90 {
 91     for(int i=head[u];i;i=edge[i].next)
 92     {
 93         int to=edge[i].to;
 94         if(to==fa)continue;
 95         dfs(to,u);
 96         rt[u]=merge(rt[u],rt[to],1,R);
 97     }
 98     if(tr[u].sz)res[u]=tr[rt[u]].ans;
 99 }
100 
101 signed main()
102 {
103     sc("%d%d",&n,&m);
104     for(int i=1;i<n;++i)
105     {
106         int u,v;
107         sc("%d%d",&u,&v);
108         add(u,v);
109         add(v,u);
110     }
111     dfs1(1,0);
112     top=0;
113     for(int i=1;i<=n;++i)rt[i]=++top;
114     for(int i=1;i<=m;++i)
115     {
116         int u,v,val;
117         sc("%d%d%d",&u,&v,&val);
118         int lca=LCA(u,v);
119         insert(rt[u],1,R,val,1);
120         insert(rt[v],1,R,val,1);
121         insert(rt[lca],1,R,val,-1);
122         if(f[lca][0])
123             insert(rt[f[lca][0]],1,R,val,-1);
124     }
125     dfs(1,0);
126     for(int i=1;i<=n;++i)
127         pr("%d
",res[i]);
128     return 0;
129 }

 

以上是关于权值线段树-动态开点-合并(P4556 [Vani有约会]雨天的尾巴的主要内容,如果未能解决你的问题,请参考以下文章

P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)

P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)

P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)

P4556 [Vani有约会]雨天的尾巴 (线段树合并 + 树上差分)

LG4556 [Vani有约会]雨天的尾巴 动态开点线段树+线段树合并

P4556 [Vani有约会]雨天的尾巴 树链剖分 线段树合并