LINK:情报中心

神题!

写了一下午 写到肚子疼.

调了一晚上 调到ex

用的是网上dalao的方法 跑的挺快的.

对于链的暴力 我不太会kk.

直接说正解吧:

分类讨论两种情况:

1 答案的两条链的LCA不重合.

2 答案的两条链的LCA重合了.

会造成这两种讨论是因为我们无法确定如果LCA重合了 固定那条重合的链 另外一个方向上的那两条链是否重合了.

其他blog里有配图 我就不放了直接口胡.

前者维护一下两条链第一次重合的地方.

然后使用线段树合并的时候来统计答案.

这个地方要注意细节的处理是否恰当.

后者 利用虚树来针对某个LCA处求答案.

是在两个支线交汇处使用树的直径的维护两个端点的方法来求出最大值.

也同时注意细节的处理.

难写难调.

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define r(x) t[x].r
#define l(x) t[x].l
#define mx1(x) t[x].mx1
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;
}
inline ll Read()
{
RE ll x=0,f=1;RE char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;
}
const int MAXN=50010;
int n,m,len,T,maxx=50000<<1,id,cnt,rt,top,now;
int Log[MAXN<<1],dfn[MAXN],q[MAXN<<2],f[MAXN<<1][20],root[MAXN],d[MAXN];
int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],e[MAXN<<1],fa[MAXN],vis[MAXN];
ll dis[MAXN],ans;
vector<pair<int,ll> >g[MAXN];
inline void add(int x,int y,int z){ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;}
struct wy{int l,r;ll mx1,mx2;}t[MAXN*40];
struct jl{int x,y;ll z;jl(){}jl(int _a,int _b,ll _z){x=_a;y=_b;z=_z;}};
struct xn
{
jl a,b;ll d;
xn(){}
xn(jl _a,jl _b,ll _d){a=_a;b=_b;d=_d;}
inline ll operator <(xn b){return d<b.d;}
}w[MAXN];
vector<jl>s[MAXN];
inline void dfs(int x,int father)
{
f[++cnt][0]=x;dfn[x]=cnt;d[x]=d[father]+1;fa[x]=father;
go(x)if(tn!=fa[x])
dis[tn]=dis[x]+e[i],dfs(tn,x),f[++cnt][0]=x;
}
inline int cmp(int x,int y){return d[x]<d[y]?x:y;}
inline int LCA(int x,int y)
{
x=dfn[x];y=dfn[y];
if(x>y)swap(x,y);
int z=Log[y-x+1];
return cmp(f[x][z],f[y-(1<<z)+1][z]);
}
inline bool cmp1(int x,int y){return dfn[x]<dfn[y];}
inline ll dist(int x,int y){return dis[x]+dis[y]-dis[LCA(x,y)]*2;}
struct solve1//solve 1.
{
inline void pushup(int p)
{
mx1(p)=max(mx1(l(p)),mx1(r(p)));
mx2(p)=max(mx2(l(p)),mx2(r(p)));
}
inline void insert(int &p,int l,int r,int x,ll c1,ll c2)
{
if(!p)p=++id,t[p]=t[0];
if(l==r){mx1(p)=max(mx1(p),c1);mx2(p)=max(mx2(p),c2);return;}
int mid=(l+r)>>1;
if(x<=mid)insert(l(p),l,mid,x,c1,c2);
else insert(r(p),mid+1,r,x,c1,c2);
pushup(p);
}
inline int merge(int l,int r,int x,int y)
{
if(!x||!y)return x|y;
if(l==r)
{
mx1(x)=max(mx1(x),mx1(y));
mx2(x)=max(mx2(y),mx2(x));
return x;
}
ans=max(ans,mx1(l(x))+mx2(r(y))-dis[now]);
ans=max(ans,mx1(l(y))+mx2(r(x))-dis[now]);
int mid=(l+r)>>1;
l(x)=merge(l,mid,l(x),l(y));
r(x)=merge(mid+1,r,r(x),r(y));
pushup(x);return x;
}
inline void change(int &p,int l,int r,int x)
{
if(!p)return;
if(l==r){p=0;return;}
int mid=(l+r)>>1;
if(x<=mid)change(l(p),l,mid,x);
else change(r(p),mid+1,r,x);
if(!l(p)&&!r(p))p=0;
else pushup(p);
}
inline void dfs(int x)
{
go(x)if(tn!=fa[x])
{
dfs(tn);
change(root[tn],1,n,d[x]);now=x;
root[x]=merge(1,n,root[x],root[tn]);
}
now=x;
vep(0,(int)g[x].size(),j)
{
int r=0;
insert(r,1,n,d[g[x][j].F],g[x][j].S,g[x][j].S+dis[g[x][j].F]);
root[x]=merge(1,n,root[x],r);
}
}
inline void solve()
{
dfs(1);
rep(1,n,i)root[i]=0,g[i].clear();id=0;
}
}S1;
struct solve2
{
inline xn calc(jl a,jl b)
{
ll dd=dist(a.x,b.x)+a.z+b.z;
ans=max(ans,dd/2-dis[now]);
return xn(a,b,dd);
}
inline void merge(xn &A,xn &B)
{
if(A.d==-INF){A=B;B.d=-INF;return;}
if(B.d==-INF)return;
if(now!=rt)
{
xn W=max(calc(A.a,B.a),calc(A.a,B.b));
W=max(W,calc(A.b,B.a));W=max(W,calc(A.b,B.b));
A=max(A,B);A=max(A,W);
}
B.d=-INF;
}
inline void calc()
{
int cc=0;top=0;
vep(0,(int)s[rt].size(),j)
{
q[++top]=s[rt][j].x;q[++top]=s[rt][j].y;
jl a=jl(q[top-1],0,s[rt][j].z+dis[q[top]]);
jl b=jl(q[top],0,s[rt][j].z+dis[q[top-1]]);
xn A=xn(a,a,a.z<<1);xn B=xn(b,b,b.z<<1);
merge(w[now=q[top]],A);merge(w[now=q[top-1]],B);
}
sort(q+1,q+1+top,cmp1);
vis[++cc]=rt;q[0]=rt;
rep(1,top,i)
{
if(q[i]==q[i-1])continue;
if(cc==1){vis[++cc]=q[i];continue;}
int lca=LCA(q[i],vis[cc]);
while(cc>1&&d[lca]<=d[vis[cc-1]])
{
merge(w[now=vis[cc-1]],w[vis[cc]]);
--cc;
}
if(vis[cc]!=lca)merge(w[now=lca],w[vis[cc]]),vis[cc]=lca;
vis[++cc]=q[i];
}
while(cc>1)
{
merge(w[now=vis[cc-1]],w[vis[cc]]);
--cc;
}
w[rt].d=-INF;
//rep(1,top,i)if(w[q[i]].d!=-INF)cout<<"ww"<<endl;
}
inline void solve()
{
rep(1,n,i)w[i].d=-INF;
rep(1,n,i)if(s[i].size()>1)rt=i,calc();
rep(1,n,i)s[i].clear();
}
}S2;
int main()
{
//freopen("1.in","r",stdin);
get(T);mx1(0)=mx2(0)=-INF;
rep(2,maxx,i)Log[i]=Log[i>>1]+1;
while(T--)
{
ans=-INF;cnt=0;len=0;
rep(1,n,i)lin[i]=0;
get(n);
rep(2,n,i)
{
int get(x),get(y),get(z);
add(x,y,z);add(y,x,z);
}
dfs(1,0);
rep(1,Log[cnt],j)
rep(1,cnt-(1<<j)+1,i)f[i][j]=cmp(f[i][j-1],f[i+(1<<(j-1))][j-1]);
//put(dis[4]);
get(m);
rep(1,m,i)
{
int get(x),get(y);ll z=Read();
if(x==y)continue;
int lca=LCA(x,y);ll cc=dist(x,y)-z;
if(x!=lca)g[x].pb(mk(lca,cc));
if(y!=lca)g[y].pb(mk(lca,cc));
s[lca].pb(jl(x,y,cc-z));
}
S1.solve();
S2.solve();
//cout<<ans<<' '<<-INF<<' '<<(ans<-INF)<<endl;
if(ans<-inf)puts("F");
else putl(ans);
}
return 0;
}

luogu P4775 [NOI2018]情报中心 线段树合并 虚树 树的直径trick的更多相关文章

  1. BZOJ5419[Noi2018]情报中心——线段树合并+虚树+树形DP

    题目链接: [NOI2018]情报中心 题目大意:给出一棵n个节点的树,边有非负边权,并给出m条链,对于每条链有一个代价,要求选出两条有公共边的链使两条链的并的边权和-两条链的代价和最大. 花了一天的 ...

  2. UOJ#397. 【NOI2018】情报中心 线段树合并 虚树

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ397.com 前言 这真可做吗?只能贺题解啊-- 题解 我们称一条路径的 LCA 为这条路径两端点的 LCA. 我们将相交 ...

  3. luogu P3180 [HAOI2016]地图 仙人掌 线段树合并 圆方树

    LINK:地图 考虑如果是一棵树怎么做 权值可以离散 那么可以直接利用dsu on tree+树状数组解决. 当然 也可以使用莫队 不过前缀和比较难以维护 外面套个树状数组又带了个log 套分块然后就 ...

  4. BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)

    标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...

  5. Codeforces 1276F - Asterisk Substrings(SAM+线段树合并+虚树)

    Codeforces 题面传送门 & 洛谷题面传送门 SAM hot tea %%%%%%% 首先我们显然可以将所有能够得到的字符串分成六类:\(\varnothing,\text{*},s, ...

  6. BZOJ3307雨天的尾巴——线段树合并

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来N ...

  7. P5666-[CSP-S2019]树的重心【树状数组】

    正题 题目链接:https://www.luogu.com.cn/problem/P5666 题目大意 给出\(n\)个点的一棵树,对于每条边割掉后两棵树重心编号和. \(1\leq T\leq 5, ...

  8. UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)

    NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...

  9. bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并)

    bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并) bzoj Luogu 给出一个字符串 $ S $ 及 $ q $ 次询问,每次询问一个字符串 $ T $ ...

随机推荐

  1. 常见的H5移动端Web页面Bug问题解决方案总汇

    解决jquery ajax调用远程接口的跨域问题 首先,接口必须允许远程调用.这是后端或者运维的事情.你必须保证你得到的一个接口是允许远程调用的.否则,就没啥了. $.ajax({ type:'get ...

  2. The Meaningless Game 思维题

    题目描述 Slastyona and her loyal dog Pushok are playing a meaningless game that is indeed very interesti ...

  3. day17 作业

    目录 一.编写函数(函数执行的时间用time.sleep(n)模拟) 二.编写装饰器,为函数加上统计时间的功能 三.编写装饰器,为函数加上认证的功能 四.编写装饰器,为多个函数加上认证的功能(用户的账 ...

  4. Spring-boot 启动报错 调试小技巧

    描述: 我们在启动spring-boot,spring-cloud 项目时,是不是经常 遇到报错,但是在控制台 没有能找到 具体 报错信息,只是 提示,启动失败,缺乏具体的报错信息,这样就很不方便我们 ...

  5. DVWA学习记录 PartⅤ

    File Upload 1. 题目 File Upload,即文件上传漏洞,通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文 ...

  6. python数据处理(七)之数据探索和分析

    1.探索数据 1.1 安装agate库 1.2 导入数据 1.3 探索表函数 a.排序 b.最值,均值 c.清除缺失值 d.过滤 e.百分比 1.4 连结多个数据集 a.捕捉异常 b.去重 c.缺失数 ...

  7. 数据可视化之DAX篇(五) 使用PowerBI的这两个函数,灵活计算各种占比

    https://zhuanlan.zhihu.com/p/57861350 计算个体占总体的比例是一个很常见的分析方式,它很简单,就是两个数字相除,但是当需要计算的维度.总体的范围发生动态变化时,如何 ...

  8. 服务器创建tensorflow环境,nni自动调参记录

    一.anaconda安装记录 1.1 下载安装脚本:wget https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh 1.2 ...

  9. bzoj3381[Usaco2004 Open]Cave Cows 2 洞穴里的牛之二*

    bzoj3381[Usaco2004 Open]Cave Cows 2 洞穴里的牛之二 题意: RMQ问题.序列长度≤25000,问题数≤25000. 题解: 倍增. 代码: #include < ...

  10. OSCP Learning Notes - Buffer Overflows(1)

    Introduction to Buffer Overflows Anatomy of Memory Anatomy of the Stack Fuzzing Tools: Vulnserver -  ...