[loj2339]通道
类似于[loj2553]
对第一棵树边分治,对第二棵树建立虚树,并根据直径合并的性质来处理第三棵树(另外在第三棵树中计算距离需要使用dfs序+ST表做到$o(1)$优化)
总复杂度为$o(n\log^{2}n)$,可以通过

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define ll long long
5 #define pii pair<int,int>
6 #define vi vector<int>
7 #define fi first
8 #define se second
9 struct Edge{
10 int nex,to;
11 ll len;
12 };
13 int n;
14 ll ans,val[N];
15 ll calc(vi x,vi y);
16 ll dis3(int x,int y);
17 namespace T1{
18 int m,E,rt,x,y,head[N<<1],sz[N<<1],vis[N<<1];
19 ll z,dep[N<<1];
20 vi v,vx,vy;
21 vector<pair<int,ll> >e[N<<1];
22 Edge edge[N<<2];
23 void add(int x,int y,ll z){
24 edge[E]=Edge{head[x],y,z};
25 head[x]=E++;
26 }
27 void dfs(int k,int fa,ll s){
28 dep[k]=s;
29 for(int i=head[k];i!=-1;i=edge[i].nex)
30 if (edge[i].to!=fa)dfs(edge[i].to,k,s+edge[i].len);
31 v.clear();
32 for(int i=head[k];i!=-1;i=edge[i].nex)
33 if (edge[i].to!=fa)v.push_back(edge[i].to);
34 int lst=k;
35 for(int i=0;i+2<v.size();i++){
36 e[lst].push_back(make_pair(v[i],dep[v[i]]-dep[k]));
37 e[lst].push_back(make_pair(++m,0));
38 lst=m;
39 }
40 if (v.size()){
41 e[lst].push_back(make_pair(v.back(),dep[v.back()]-dep[k]));
42 v.pop_back();
43 if (v.size())e[lst].push_back(make_pair(v.back(),dep[v.back()]-dep[k]));
44 }
45 }
46 void build(){
47 m=n;
48 memset(head,-1,sizeof(head));
49 for(int i=1;i<n;i++){
50 scanf("%d%d%lld",&x,&y,&z);
51 add(x,y,z),add(y,x,z);
52 }
53 dfs(1,0,0);
54 E=0;
55 memset(head,-1,sizeof(head));
56 for(int i=1;i<=m;i++)assert(e[i].size()<=2);
57 for(int i=1;i<=m;i++)
58 for(int j=0;j<e[i].size();j++){
59 add(i,e[i][j].fi,e[i][j].se);
60 add(e[i][j].fi,i,e[i][j].se);
61 }
62 }
63 void get_sz(int k,int fa){
64 sz[k]=1;
65 for(int i=head[k];i!=-1;i=edge[i].nex)
66 if ((!vis[i>>1])&&(edge[i].to!=fa)){
67 get_sz(edge[i].to,k);
68 sz[k]+=sz[edge[i].to];
69 }
70 }
71 void get_rt(int k,int fa,int s){
72 for(int i=head[k];i!=-1;i=edge[i].nex)
73 if ((!vis[i>>1])&&(edge[i].to!=fa)){
74 get_rt(edge[i].to,k,s);
75 if ((s<=3*sz[edge[i].to]+1)&&(3*sz[edge[i].to]<=(s+1<<1)))rt=(i>>1);
76 }
77 }
78 void get_v(vi &v,int k,int fa,ll s){
79 if (k<=n){
80 val[k]=s;
81 v.push_back(k);
82 }
83 for(int i=head[k];i!=-1;i=edge[i].nex)
84 if ((!vis[i>>1])&&(edge[i].to!=fa))get_v(v,edge[i].to,k,s+edge[i].len);
85 }
86 void divide(int k){
87 get_sz(k,0);
88 if (sz[k]==1)return;
89 get_rt(k,0,sz[k]);
90 k=rt,vis[k]=1;
91 vx.clear(),vy.clear();
92 get_v(vx,edge[k<<1].to,0,0);
93 get_v(vy,edge[(k<<1)|1].to,0,0);
94 ans=max(ans,calc(vx,vy)+edge[k<<1].len);
95 divide(edge[k<<1].to);
96 divide(edge[(k<<1)|1].to);
97 }
98 };
99 namespace T2{
100 int E,x,y,head[N],dfn[N],sh[N],f[N][20],st[N];
101 ll z,ans,dep[N];
102 pii mx[N][2];
103 vi v0,v,e[N];
104 Edge edge[N<<1];
105 bool cmp(int x,int y){
106 return dfn[x]<dfn[y];
107 }
108 void add(int x,int y,ll z){
109 edge[E]=Edge{head[x],y,z};
110 head[x]=E++;
111 }
112 int lca(int x,int y){
113 if (sh[x]<sh[y])swap(x,y);
114 for(int i=19;i>=0;i--)
115 if (sh[f[x][i]]>=sh[y])x=f[x][i];
116 if (x==y)return x;
117 for(int i=19;i>=0;i--)
118 if (f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
119 return f[x][0];
120 }
121 void dfs(int k,int fa,int s1,ll s2){
122 dfn[k]=++dfn[0],sh[k]=s1,dep[k]=s2;
123 f[k][0]=fa;
124 for(int i=1;i<20;i++)f[k][i]=f[f[k][i-1]][i-1];
125 for(int i=head[k];i!=-1;i=edge[i].nex)
126 if (edge[i].to!=fa)dfs(edge[i].to,k,s1+1,s2+edge[i].len);
127 }
128 void build(){
129 memset(head,-1,sizeof(head));
130 for(int i=1;i<n;i++){
131 scanf("%d%d%lld",&x,&y,&z);
132 add(x,y,z),add(y,x,z);
133 }
134 dfs(1,1,0,0);
135 }
136 void build(vi v0){
137 bool flag=0;
138 for(int i=0;i<v0.size();i++)
139 if (v0[i]==1)flag=1;
140 if (!flag){
141 v0.push_back(1);
142 v.push_back(1);
143 }
144 sort(v0.begin(),v0.end(),cmp);
145 st[0]=st[1]=1;
146 for(int i=1;i<v0.size();i++){
147 int k=lca(v0[i],st[st[0]]);
148 while ((st[0]>1)&&(dfn[st[st[0]-1]]>=dfn[k])){
149 e[st[st[0]-1]].push_back(st[st[0]]);
150 st[0]--;
151 }
152 if (k!=st[st[0]]){
153 v.push_back(k);
154 e[k].push_back(st[st[0]]);
155 st[st[0]]=k;
156 }
157 st[++st[0]]=v0[i];
158 }
159 while (st[0]>1){
160 e[st[st[0]-1]].push_back(st[st[0]]);
161 st[0]--;
162 }
163 }
164 ll merge_ans(pii x,pii y){
165 return max(max(dis3(x.fi,y.fi),dis3(x.fi,y.se)),max(dis3(x.se,y.fi),dis3(x.se,y.se)));
166 }
167 pii merge(pii x,pii y){
168 pii ans=x;
169 if (dis3(y.fi,y.se)>dis3(ans.fi,ans.se))ans=y;
170 if (dis3(x.fi,y.fi)>dis3(ans.fi,ans.se))ans=make_pair(x.fi,y.fi);
171 if (dis3(x.fi,y.se)>dis3(ans.fi,ans.se))ans=make_pair(x.fi,y.se);
172 if (dis3(x.se,y.fi)>dis3(ans.fi,ans.se))ans=make_pair(x.se,y.fi);
173 if (dis3(x.se,y.se)>dis3(ans.fi,ans.se))ans=make_pair(x.se,y.se);
174 return ans;
175 }
176 void dfs(int k){
177 for(int i=0;i<e[k].size();i++){
178 dfs(e[k][i]);
179 ans=max(ans,merge_ans(mx[k][0],mx[e[k][i]][1])-(dep[k]<<1));
180 ans=max(ans,merge_ans(mx[k][1],mx[e[k][i]][0])-(dep[k]<<1));
181 mx[k][0]=merge(mx[k][0],mx[e[k][i]][0]);
182 mx[k][1]=merge(mx[k][1],mx[e[k][i]][1]);
183 }
184 }
185 ll calc(vi vx,vi vy){
186 ans=0,v0.clear();
187 for(int i=0;i<vx.size();i++)v0.push_back(vx[i]);
188 for(int i=0;i<vy.size();i++)v0.push_back(vy[i]);
189 for(int i=0;i<v0.size();i++)val[v0[i]]+=dep[v0[i]];
190 v=v0,build(v0);
191 for(int i=0;i<v.size();i++)mx[v[i]][0]=mx[v[i]][1]=make_pair(-1,-1);
192 for(int i=0;i<vx.size();i++)mx[vx[i]][0]=make_pair(vx[i],vx[i]);
193 for(int i=0;i<vy.size();i++)mx[vy[i]][1]=make_pair(vy[i],vy[i]);
194 dfs(1);
195 for(int i=0;i<v.size();i++)e[v[i]].clear();
196 return ans;
197 }
198 };
199 namespace T3{
200 int m,E,x,y,lg[N<<1],head[N],pos[N];
201 ll z,ans,dep[N<<1],f[N<<1][20];
202 Edge edge[N<<1];
203 void add(int x,int y,ll z){
204 edge[E]=Edge{head[x],y,z};
205 head[x]=E++;
206 }
207 ll get_min(int x,int y){
208 int m=lg[y-x+1];
209 return min(f[x][m],f[y-(1<<m)+1][m]);
210 }
211 ll dis(int x,int y){
212 x=pos[x],y=pos[y];
213 if (x>y)swap(x,y);
214 return dep[x]+dep[y]-(get_min(x,y)<<1);
215 }
216 void dfs(int k,int fa,ll s){
217 dep[++m]=s,pos[k]=m;
218 for(int i=head[k];i!=-1;i=edge[i].nex)
219 if (edge[i].to!=fa){
220 dfs(edge[i].to,k,s+edge[i].len);
221 dep[++m]=s;
222 }
223 }
224 void build(){
225 memset(head,-1,sizeof(head));
226 for(int i=1;i<n;i++){
227 scanf("%d%d%lld",&x,&y,&z);
228 add(x,y,z),add(y,x,z);
229 }
230 dfs(1,0,0);
231 lg[0]=-1;
232 for(int i=1;i<=m;i++)lg[i]=lg[i>>1]+1;
233 for(int i=m;i;i--){
234 f[i][0]=dep[i];
235 for(int j=1;j<20;j++)f[i][j]=min(f[i][j-1],f[min(i+(1<<j-1),m)][j-1]);
236 }
237 }
238 };
239 ll calc(vi vx,vi vy){
240 return T2::calc(vx,vy);
241 }
242 ll dis3(int x,int y){
243 if ((x<0)||(y<0))return -1e18;
244 return val[x]+val[y]+T3::dis(x,y);
245 }
246 int main(){
247 scanf("%d",&n);
248 T1::build();
249 T2::build();
250 T3::build();
251 T1::divide(1);
252 printf("%lld\n",ans);
253 return 0;
254 }
[loj2339]通道的更多相关文章
- 【loj2339】【WC2018】通道
题目 三棵带边权的树,求 \[ dis1(u,v) + dis2(u,v) + dis3(u,v) \] 的最大值 \(1 \le n \le 10^5\) 题解 对\(T_1\)做边分治,把分治边的 ...
- Paypal开发中遇到请求被中止: 未能创建 SSL/TLS 安全通道及解决方案
最近在基于ASP.NET上开发了Paypal支付平台,在ASP.NET开发的过程中没有遇到这个问题,但是引用到MVC开发模式中的时候就出现了"未能创建 SSL/TLS 安全通道及解决方案&q ...
- JAVA NIO Socket通道
DatagramChannel和SocketChannel都实现定义读写功能,ServerSocketChannel不实现,只负责监听传入的连接,并建立新的SocketChannel,本身不传输数 ...
- 学习 opencv---(4) 分离颜色通道 && 多通道混合
上篇文章中我们讲到了使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像混合操作. 而为了更好地观察一些图像材料的特征,有时需要对R ...
- 关于QImage提取单色通道方法(vector)
转载请标明处: 作者:微微苏荷 本文地址:关于QImage提取单色通道方法(vector) 近日,用QT和mxnet结合做一个图像识别的demo.遇到需要把图片从QImage转为vector单色分离的 ...
- 基于暗通道优先算法的去雾应用(Matlab/C++)
基于暗通道优先的单幅图像去雾算法(Matlab/C++) 算法原理: 参见论文:Single Image Haze Removal Using Dark Channel Pri ...
- Java NIO4:Socket通道
Socket通道 上文讲述了通道.文件通道,这篇文章来讲述一下Socket通道,Socket通道与文件通道有着不一样的特征,分三点说: 1.NIO的Socket通道类可以运行于非阻塞模式并且是可选择的 ...
- Java NIO3:通道和文件通道
通道是什么 通道式(Channel)是java.nio的第二个主要创新.通道既不是一个扩展也不是一项增强,而是全新的.极好的Java I/O示例,提供与I/O服务的直接连接.Channel用于在字节缓 ...
- IO通道
本文原创,转载需标明原处. 通道,主要负责传输数据,相当于流,但流只能是输入或输出类型中的其一,而通道则可以兼并二者. 通道的基类是:Channel boolean isOpen() void clo ...
随机推荐
- MyCat的快速搭建
1. 概述 老话说的好:一个好汉三个帮,一个人再聪明.再有本事,也要借助他人的力量,才能成功. 言归正传,今天我们来聊聊 MyCat的快速搭建. 2. 场景介绍 服务器A IP:192.168.1.2 ...
- Azure Devops实践(5)- 构建springboot项目打包docker镜像及容器化部署
使用Azure Devops构建java springboot项目,创建镜像并容器化部署 1.创建一个springboot项目,我用现有的项目 目录结构如下,使用provider项目 在根目录下添加D ...
- .Net Core with 微服务 - 使用 AgileDT 快速实现基于可靠消息的分布式事务
前面对于分布式事务也讲了好几篇了(可靠消息最终一致性 分布式事务 - TCC 分布式事务 - 2PC.3PC),但是还没有实战过.那么本篇我们就来演示下如何在 .NET 环境下实现一个基于可靠消息的分 ...
- 分片利器 AutoTable:为用户带来「管家式」分片配置体验
在<DistSQL:像数据库一样使用 Apache ShardingSphere>一文中,Committer 孟浩然为大家介绍了 DistSQL 的设计初衷和语法体系,并通过实战操作展示了 ...
- storm卡顿修改
最近的webstorm越来越卡了,有时候甚至会弹出 Out of memory的窗口,提示要设置 xmx的值, 8G内存跑你这小软件还会不够用???要内存?给你,看你还会不会卡成翔! 于是果断给x ...
- 舌头算法的C++实现
观察生活,我们不难发现,吃饭的时候,有时候左边的东西会到右边来,这是为什么呢?就是舌头的作用了. 下面的代码将模拟舌头的运动: #include <iostream> #include & ...
- 敏捷 Scrum Master 的難點
什麼是 Scrum Master? Scrum master 是一個團隊角色,負責確保團隊遵守敏捷方法和原則並符合團隊的流程和實踐. Scrum Master 促進敏捷開發團隊成員之間的協作.Scru ...
- Redis:学习笔记-04
Redis:学习笔记-04 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 10. Redis主从复制 1 ...
- 混合开发框架Flutter
Flutter开发简介与其他的混合开发的对比 为什么要使用Flutter? 跨平台技术简介 Hybrid技术简介 QT简介 Flutter简介 为什么要使用Flutter? Flutter有什么优势? ...
- spring session实现session统一管理(jdbc实现)
最近在看一些关于spring session 的知识,特做一个笔记记录一下. 在项目中经常会遇到这么一种情况,同一个web项目有时需要部署多份,然后使用nginx实现负载均衡,那么遇到的问题就是,部署 ...