[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 ...
随机推荐
- 市区择房分析(ArcPy实现)
1, 背景 如何找到环境好.购物方便.小孩上学方便的居住区地段是购房者最关心的问题.因此购房者就需要从总体上对商品房的信息进行研究分析,选择最适宜的购房地段. 2,目的 学会利用缓冲区分析和叠置分析解 ...
- 洛谷2149 Elaxia的路线(dp+最短路)
QwQ好久没更新博客了,颓废了好久啊,来补一点东西 题目大意 给定两个点对,求两对点间最短路的最长公共路径. 其中\(n,m\le 10^5\) 比较简单吧 就是跑四遍最短路,然后把最短路上的边拿出来 ...
- this指向与call,apply,bind
this指向与call,apply,bind ❝ 「this」问题对于每个前端同学来说相信都不陌生,在平时开发中也经常能碰到,有时候因为「this」还踩过不少坑,并且「this」问题在面试题中出现的概 ...
- SSM框架项目的mvc拦截器
为了防止用户在不登录的情况下通过并接请求直接访问系统,我们需要通过session和拦截器来防止这样的情况. 拦截器的配置: 为拦截器建立一个包:interceptor,并在包里建立 LoginInte ...
- 让全链路压测变得更简单!Takin2.0重磅来袭!
自Takin社区版1.0发布两个多月以来,有很多测试同学陆续在各自的工作中运用了起来,其中包括金融.电商.物流.出行服务等行业.这个过程中我们收到了很多同学的反馈建议,同时也了解到很多同学在落地全链路 ...
- UltraSoft - Alpha - 发布声明
DDL_Killer Alpha版本发布声明 1. Alpha 阶段功能描述与版本实现 功能描述 设计原型 Alpha实现 登陆界面 注册界面 首页 日历视图 事项详情页 新建事项 列表视图 课程视图 ...
- springboot多配置环境
在我们的开发过程中,经常会有多套配置环境,比如开发环境(dev),测试环境(test),生产环境(prod)等,在各个环境中我们需要使用到不同的配置,那么在springboot中是如何做到的呢? 1. ...
- 这一篇 K8S(Kubernetes)我觉得可以了解一下!!!
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 什么是Kubernetes? Kubernetes 是Google开源的分布式容器管理平台,是为 ...
- gdal3.1.0+VS2017+geos+kml编译总结
1.简介 gdal3.1.0编译过程中必须依赖proj,编译gdal必须要编译proj,proj的编译需要sqlite3,因此想要编译gdal3.1.0需要先编译proj和sqlite3 2.关于sq ...
- stm32学习笔记之串口通信
在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...