随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3296

 一、题目描述:

  给定一棵以 1 为根,n 个节点的树。设 d(u,x) 为 u 的子树中到 u 距离为 x 的节点数。对于每个点,求一个最小的 k,使得 d(u,k) 最大。n<=1e6。


 二、做题思路:

  很明显是一个线段树合并的题,但是线段树里面放什么呢?设当前节点为 u:

  如果放的是距 u 距离为 x 的点的数量,那么在合并给父亲的时候就会出现 +1 的问题。

  如果存的是深度就没问题了,可以直接合并,减去当前节点的深度即为答案。

  注意要动态开点,否则会炸空间。时间复杂度 O(nlogn) 。


 三、完整代码:

复制代码
 1 #include<iostream>
 2 #include<cstring>
 3 #define N 1000010
 4 #define ls(p) t[p].ls
 5 #define rs(p) t[p].rs
 6 using namespace std;
 7 int n,u1,v1,tot;
 8 int du[N],fa[N],ans[N],ro[N];
 9 struct Seg_tree{
10     int ls,rs;
11     int mx,sum;
12 }t[N*25];
13 struct EDGE{
14     int v,nxt;
15 }edge[N*2];
16 int head[N],cnt;
17 void add(int u,int v)
18 {
19     edge[++cnt].v=v;
20     edge[cnt].nxt=head[u];
21     head[u]=cnt;
22 }
23 void dfs1(int now,int d,int ff)
24 {
25     du[now]=d;fa[now]=ff;
26     for(int i=head[now];i!=-1;i=edge[i].nxt)
27         if(!du[edge[i].v])    dfs1(edge[i].v,d+1,now);
28 }
29 void push_up(int rt)
30 {
31     if(t[ls(rt)].sum>=t[rs(rt)].sum)
32         t[rt].sum=t[ls(rt)].sum,t[rt].mx=t[ls(rt)].mx;
33     if(t[ls(rt)].sum<t[rs(rt)].sum)
34         t[rt].sum=t[rs(rt)].sum,t[rt].mx=t[rs(rt)].mx;
35 }
36 void update(int &rt,int l,int r,int x)
37 {
38     if(!rt)    rt=++tot;
39     if(l==r)
40     {
41         t[rt].mx=l;
42         t[rt].sum++;
43         return ;
44     }
45     int mid=(l+r)>>1;
46     if(x<=mid)    update(ls(rt),l,mid,x);
47     if(x>mid)    update(rs(rt),mid+1,r,x);
48     push_up(rt);
49 }
50 int merge(int p,int q,int l,int r)
51 {
52     if(!q)    return p;
53     if(!p)    return q;
54     if(l==r)
55     {
56         t[p].sum+=t[q].sum;
57         return p;
58     }
59     int mid=(l+r)>>1;
60     ls(p)=merge(ls(p),ls(q),l,mid);
61     rs(p)=merge(rs(p),rs(q),mid+1,r);
62     push_up(p);
63     return p;
64 }
65 void dfs2(int now)
66 {
67     for(int i=head[now];i!=-1;i=edge[i].nxt)
68         if(edge[i].v!=fa[now])
69         {
70             dfs2(edge[i].v);
71             ro[now]=merge(ro[now],ro[edge[i].v],1,n);
72         }
73     ans[now]=t[ro[now]].mx-du[now];
74 }
75 int main()
76 {
77     ios::sync_with_stdio(false);
78     cin.tie(0);cout.tie(0);
79     cin>>n;
80     memset(head,-1,sizeof(head));
81     for(int i=1;i<n;i++)
82     {
83         cin>>u1>>v1;
84         add(u1,v1);
85         add(v1,u1);
86     }
87     dfs1(1,1,0);
88     for(int i=1;i<=n;i++)
89         update(ro[i],1,n,du[i]);
90     dfs2(1);
91     for(int i=1;i<=n;i++)
92         cout<<ans[i]<<'\n';
93     return 0;
94 }
复制代码

 四、写题心得:

  拜托,这是紫题诶!!!真的很高兴的好吧!!!加油!

posted on   trh0630  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示