链接

点击跳转

题解

做法一(TLE):

维护每个点到最远的儿子的距离disxdis_xdisx​
设yyy的左右儿子为a,ba,ba,b,那么以yyy为lcalcalca的最长链的长度就是disa+disbdis_a+dis_bdisa​+disb​

每次给一个叶子挂上两个孩子,都会影响到包含这个叶子结点的一条链的disdisdis和fff值,拿树剖+线段树维护一下就可以了

时间复杂度O(nlog2n)O(nlog^2n)O(nlog2n)

做法二(TLE):
分析同上,拿lctlctlct去维护这个东西,时间复杂度O(nlogn)O(nlogn)O(nlogn)

都知道splaysplaysplay常数大,所以TTT掉也是没办法的事请

做法三(AC):

要用到一定的树的知识,直径的求法就是从任意一个点出发找到离这个点最远的点,假设这个最远的点是uuu,那么可以证明uuu肯定是直径的端点,再从uuu出发找最远点vvv,则路径(u,v)(u,v)(u,v)就是直径

考虑新加入的点xxx,如果新树的直径包含xxx,那么要么是(u,x)(u,x)(u,x),要么是(v,x)(v,x)(v,x),直接更新一下就好了

代码一(TLE)

#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 1000010
#define maxe 1000010
#define maxk 19
#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
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 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;}
}G;
struct ShuLianPouFen
{int size[maxn], top[maxn], tid[maxn], tim, untid[maxn], deep[maxn], son[maxn], fa[maxn];void dfs1(Graph &G, int pos){int p, v;size[pos]=1;for(p=G.head[pos];p;p=G.next[p]){if((v=G.to[p])==fa[pos])continue;fa[v]=pos;deep[v]=deep[pos]+1;dfs1(G,v);if(size[v]>size[son[pos]])son[pos]=v;size[pos]+=size[v];}}void dfs2(Graph &G, int pos, int tp){int p, v;top[pos]=tp;tid[pos]=++tim;untid[tid[pos]]=pos;if(son[pos])dfs2(G,son[pos],tp);for(p=G.head[pos];p;p=G.next[p])if((v=G.to[p])!=fa[pos] and v!=son[pos])dfs2(G,v,v);}void run(Graph &G, int root){tim=0;deep[root]=1;dfs1(G,root);dfs2(G,root,root);}
}sp;
struct SegmentTree
{#define inf 0x3f3f3f3fint mx[maxn<<2], add[maxn<<2], L[maxn<<2], R[maxn<<2];void maketag_add(int o, int v){add[o]+=v;mx[o]+=v;}void pushdown(int o){if(L[o]==R[o])return;if(add[o]){maketag_add(o<<1,add[o]);maketag_add(o<<1|1,add[o]);add[o]=0;}}void pushup(int o){mx[o]=max(mx[o<<1],mx[o<<1|1]);}void build(int o, int l, int r){int mid(l+r>>1);L[o]=l, R[o]=r;add[o]=0;if(l==r){return;}build(o<<1,l,mid);build(o<<1|1,mid+1,r);pushup(o);}void segadd(int o, int l, int r, int v){int mid(L[o]+R[o]>>1);if(l<=L[o] and r>=R[o]){maketag_add(o,v);return;}pushdown(o);if(l<=mid)segadd(o<<1,l,r,v);if(r>mid)segadd(o<<1|1,l,r,v);pushup(o);}int segmax(int o, int l, int r){int mid(L[o]+R[o]>>1), ans(-inf);if(l<=L[o] and r>=R[o])return mx[o];pushdown(o);if(l<=mid)ans=max(ans,segmax(o<<1,l,r));if(r>mid)ans=max(ans,segmax(o<<1|1,l,r));return ans;}#undef inf
}dep, f;
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;
void add(SegmentTree &t, int x, int y, int v)
{int tx=sp.top[x];while(tx!=sp.top[y]){t.segadd(1,sp.tid[tx],sp.tid[x],v);x=sp.fa[tx], tx=sp.top[x];}t.segadd(1,sp.tid[y],sp.tid[x],v);
}
int v[maxn];
int main()
{int q, n=4, i, cnt;q=read();G.adde(1,2), G.adde(1,3), G.adde(1,4);rep(i,q){v[i]=read();G.adde(v[i],n+1);G.adde(v[i],n+2);n+=2;}sp.run(G,1);db.run(G,1);dep.build(1,1,n);f.build(1,1,n);dep.segadd(1,sp.tid[1],sp.tid[1],+2);dep.segadd(1,sp.tid[2],sp.tid[2],+2);dep.segadd(1,sp.tid[3],sp.tid[3],+2);dep.segadd(1,sp.tid[4],sp.tid[4],+2);cnt=4;rep(i,q){int x=v[i];for(int k=maxk;~k;k--)if(db.f[x][k]!=0 and dep.segmax(1,sp.tid[db.f[x][k]],sp.tid[db.f[x][k]])<sp.deep[v[i]]+1)x=db.f[x][k];add(dep,v[i],x,+1);add(dep,cnt+1,cnt+1,+sp.deep[cnt+1]);add(dep,cnt+2,cnt+2,+sp.deep[cnt+2]);add(f,v[i],x==1?1:sp.fa[x],+1);add(f,v[i],v[i],+1);int ans=f.segmax(1,2,n);int d2, d3, d4;d2=dep.segmax(1,sp.tid[2],sp.tid[2])-1;d3=dep.segmax(1,sp.tid[3],sp.tid[3])-1;d4=dep.segmax(1,sp.tid[4],sp.tid[4])-1;ans=max(ans,d2+d3), ans=max(ans,d3+d4), ans=max(ans,d2+d4);printf("%d\n",ans);cnt+=2;}return 0;
}

代码二(TLE)

#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 1000010
#define maxe 1000010
#define maxk 19
#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
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 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;}
}G;
struct LinkCutTree
{int rev[maxn], f[maxn], ch[maxn][2], s[maxn], mx[maxn], add[maxn], v[maxn];int getwh(int x){if(f[x]==0)return -1;if(ch[f[x]][0]==x)return 0;if(ch[f[x]][1]==x)return 1;return -1;}bool isroot(int x){return getwh(x)==-1;}void maketag_rev(int x){if(x)rev[x]^=1;}void maketag_add(int x, int v){if(x)add[x]+=v;}void join(int x, int y, int wh){if(x)f[x]=y;if(y)ch[y][wh]=x;}void pushdown(int x){if(rev[x]){swap(ch[x][0],ch[x][1]);maketag_rev(ch[x][0]), maketag_rev(ch[x][1]);rev[x]=0;}if(add[x]){v[x]+=add[x];mx[x]+=add[x];maketag_add(ch[x][0],add[x]);maketag_add(ch[x][1],add[x]);add[x]=0;}}void pushup(int x){pushdown(ch[x][0]), pushdown(ch[x][1]);mx[x]=v[x];if(ch[x][0])mx[x]=max(mx[x],mx[ch[x][0]]);if(ch[x][1])mx[x]=max(mx[x],mx[ch[x][1]]);}void rotate(int x){int y=f[x], z=f[y];int c=getwh(x);if(!isroot(y))join(x,z,getwh(y));else f[x]=z;join(ch[x][!c],y,c);join(y,x,!c);pushup(y);pushup(x);}void splay(int x){int y, top(0);for(y=x;!isroot(y);y=f[y])s[++top]=y;s[++top]=y;for(;top;top--)pushdown(s[top]);while(!isroot(x)){y=f[x];if(isroot(y)){rotate(x);break;}if(getwh(x)^getwh(y))rotate(x);else rotate(y);rotate(x);}}void access(int x){int t=0;while(x){splay(x);ch[x][1]=t;pushup(x);t=x;x=f[x];}}void makeroot(int x){access(x);splay(x);maketag_rev(x);}void link(int x, int y){makeroot(x);f[x]=y;}void cut(int x, int y){makeroot(x); access(y);splay(y);if(ch[y][0]==x and ch[x][1]==0)f[x]=ch[y][0]=0;}int findroot(int x){access(x); splay(x);while(ch[x][0])pushdown(x), x=ch[x][0];splay(x);return x;}
}f, dep;
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;
void add(LinkCutTree &t, int x, int y, int v)
{t.makeroot(y);t.access(x);t.splay(x);t.maketag_add(x,v);
}
int qmax(LinkCutTree &t, int x, int y)
{t.makeroot(y);t.access(x);t.splay(x);return t.mx[x];
}
int v[maxn];
int main()
{int q, n=4, i, cnt, ans=0;q=read();G.adde(1,2), G.adde(1,3), G.adde(1,4);rep(i,q){v[i]=read();G.adde(v[i],n+1);G.adde(v[i],n+2);n+=2;}db.run(G,1);for(i=2;i<=4;i++)dep.v[i]=2;cnt=4;rep(i,q){int x=v[i];for(int k=maxk;~k;k--)if(db.f[x][k]>1){dep.splay(db.f[x][k]);if(dep.v[db.f[x][k]]<db.depth[v[i]]+1)x=db.f[x][k];}add(dep,v[i],x,+1);add(f,v[i],db.f[x][0]==1?x:db.f[x][0],+1);add(f,v[i],v[i],+1);ans=max(ans,qmax(f,v[i],db.f[x][0]==1?x:db.f[x][0]));dep.link(cnt+1,v[i]); dep.v[cnt+1]=dep.mx[cnt+1]=db.depth[cnt+1];dep.link(cnt+2,v[i]); dep.v[cnt+2]=dep.mx[cnt+1]=db.depth[cnt+2];f.link(cnt+1,v[i]);f.link(cnt+2,v[i]);int d2, d3, d4;d2=qmax(dep,2,2)-1;d3=qmax(dep,3,3)-1;d4=qmax(dep,4,4)-1;ans=max(ans,d2+d3), ans=max(ans,d3+d4), ans=max(ans,d2+d4);printf("%d\n",ans);cnt+=2;}return 0;
}

代码三(AC)

#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 1000010
#define maxe 1000010
#define maxk 19
#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
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 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;}
}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 v[maxn];
int qdis(int x, int y)
{int lca=db.q(x,y);return db.depth[x]+db.depth[y]-2*db.depth[lca];
}
int main()
{int q, n=4, i, cnt, ans=2, a, b;q=read();G.adde(1,2), G.adde(1,3), G.adde(1,4);rep(i,q){v[i]=read();G.adde(v[i],n+1);G.adde(v[i],n+2);n+=2;}db.run(G,1);a=2,b=3;cnt=4;rep(i,q){int p=qdis(a,cnt+1)>qdis(b,cnt+1)?a:b;if(qdis(p,cnt+1)>ans)ans=qdis(p,cnt+1), a=p, b=cnt+1;printf("%d\n",ans);cnt+=2;}return 0;
}

cf379F. New Year Tree相关推荐

  1. CF379F New Year Tree

    一.题目 点此看题 二.解法 回忆树直径的非dpdpdp求法,随便那一个点找到最远点,再从最远点找它的最远点就得到了直径. 这道题肯定不能暴力找,我们考虑新加入的点对直径的影响,设原来的直径端点是(A ...

  2. cf379F New Year Tree (树的直径+倍增lca)

    可以证明,如果合并两棵树,新的直径的端点一定是原来两树中直径的端点 可以把新加两个点的操作看成是把两个只有一个点的树合并到原来的树上,然后用其中的一个点去和原来树上的直径两端点更新直径就可以了 1 # ...

  3. 【倍增算法】CF379F New Year Tree 题解

    In LuoGu 题目大意: 每次在给定节点增加两个点,动态输出当时树的直径,注意强制动态. 思路详解: 对于新加入的两个节点,新树的直径必定在两个点到另一个叶子节点的距离中,否则,新树的直径肯定和原 ...

  4. 107. Binary Tree Level Order Traversal II

    题目 Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from l ...

  5. 102. Binary Tree Level Order Traversal

    题目 Binary Tree Level Order Traversal 层次遍历二叉树 链接 Given a binary tree, return the level order traversa ...

  6. Python---哈夫曼树---Huffman Tree

    今天要讲的是天才哈夫曼的哈夫曼编码,这是树形数据结构的一个典型应用. !!!敲黑板!!!哈夫曼树的构建以及编码方式将是我们的学习重点. 老方式,代码+解释,手把手教你Python完成哈夫曼编码的全过程 ...

  7. [Java]LeetCode297. 二叉树的序列化与反序列化 | Serialize and Deserialize Binary Tree

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  8. Code Forces Bear and Forgotten Tree 3 639B

    B. Bear and Forgotten Tree 3 time limit per test2 seconds memory limit per test256 megabytes inputst ...

  9. Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)

    Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈) 标签: codeforces 2017-06-02 11:41 29人阅读 ...

最新文章

  1. 面试官:你说你精通Redis,你看过持久化的配置吗?
  2. oracle object_type,Oracle TYPE OBJECT详解 | 学步园
  3. 倒置 mysql_SQL Server中的行列倒置技巧
  4. Linux负载均衡--LVS(IPVS)
  5. ROS学习--第3篇:ROS基础---创建工作空间和软件包
  6. ubuntu9.10 安装 eclipse3.5 的问题
  7. hdu 1069 Monkey and Banana (LIS)
  8. [No0000E6]C# 判断与循环
  9. [中文版] 可视化 CSS References 文档
  10. 据说这是史上最牛逼的可视化神器
  11. 换行符‘/n’和回车符‘/r’ 区别
  12. Java实训项目9:GUI学生信息管理系统 - 实现步骤 - 创建数据访问接口
  13. Debian 26 岁生日快乐!Happy DebianDay!
  14. java调用WebService接口工具
  15. 【信息系统项目管理师】重点整理:高项知识地图
  16. 1000+ Python第三方库大合集,从入门到精通,指日可待!
  17. k8s技术预研8--深入掌握Kubernetes Service
  18. 云服务器修改dns服务器为阿里云公共dns服务器
  19. hdu4416[多串后缀自动机]
  20. PHP将Word转PDF文件

热门文章

  1. java练习:金额转换,阿拉伯数字转换成中文传统形式
  2. 苹果电脑安装linux系统教程,如何在MacBook Pro Retina上安装Linux
  3. Haar+Adaboost级联分类器分解(三):利用并查集合并检测结果窗口
  4. python以垂直方式输出hello world_Python之Hello World的条件输出实例
  5. JS中的堆和栈怎么理解?
  6. request+pandas采集京东数据存入excel
  7. 数据结构——链表(java)
  8. 基于 Web 2.0 的下一代网络银行
  9. ps转手绘课程基础day01--学习笔记
  10. js--《js延时加载有哪些方式》