去年这道水题没做出来
然而今儿看到正解也是崩溃的
正解是个垃圾树剖。。
noip
什么时候开始考树剖了???
好吧去年联赛的时候还没学树剖。。。
第一遍
dfs
除了处理那些个节点的重量外顺便处理下每个节点到根的距离
其他和普通树剖没什么区别
然后读入点对,先算出每一对的
lca
和距离,记下最大距离
二分答案,因为最长的那条路线是肯定要变短的,所以二分的上界就是最长的那条
对于一个答案,一个点对的距离如果大于这个数就在线段树上覆盖一次,最后每一条边统计覆盖次数,并找出覆盖次数等于距离大于答案的点对个数的最长的一条边,然后判断最长那条是否小于等于答案加该边长
覆盖什么的和树剖路径上修改的一样
本以为要调很久没想到一下就过了
本来
1A
的然而我文件没关
T
了一次。。。
去掉文件就直接过了。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define g getchar()
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 300010
using namespace std;
inline ll read(){
ll x=0,f=1;char ch=g;
for(;ch<'0'||ch>'9';ch=g)if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=g)x=x*10+ch-'0';
return x*f;
}
inline void out(ll x){
int a[25],t=0;
if(x<0)putchar('-'),x=-x;
for(;x;x/=10)a[++t]=x%10;
for(int i=t;i;--i)putchar('0'+a[i]);
if(t==0)putchar('0');
putchar('\n');
}
struct re{int v,w,next;}ed[maxn*2];
int e,cnt,m,n,mx,lca[maxn],x[maxn],y[maxn],ans;
int sz[maxn],head[maxn],f[maxn],dis[maxn],bl[maxn],id[maxn],num[maxn],t[3*maxn],dist[maxn];
inline void ins(int x,int y,int w){ed[++e]=(re){y,w,head[x]};head[x]=e;}
void dfs1(int x){
sz[x]=1;
for(int i=head[x];i;i=ed[i].next)
if(ed[i].v!=f[x]){
f[ed[i].v]=x;dis[ed[i].v]=dis[x]+ed[i].w;
dfs1(ed[i].v);sz[x]+=sz[ed[i].v];
}
}
void dfs2(int x,int chain){
int now=0;bl[x]=chain;id[x]=++cnt;num[cnt]=x;
for(int i=head[x];i;i=ed[i].next)if(ed[i].v!=f[x]&&sz[now]<sz[ed[i].v])now=ed[i].v;
if(now)dfs2(now,chain);
for(int i=head[x];i;i=ed[i].next)if(ed[i].v!=now&&ed[i].v!=f[x])dfs2(ed[i].v,ed[i].v);
}
int lc(int x,int y){
int fx=bl[x],fy=bl[y];
for(;fx!=fy;){
if(dis[fx]<dis[fy])swap(x,y),swap(fx,fy);
x=f[fx];fx=bl[x];
}
return dis[x]<dis[y]?x:y;
}
inline void push(int k,int l,int r){if(l>=r)return;t[k<<1]+=t[k],t[k<<1|1]+=t[k];t[k]=0;}
int query(int k,int l,int r,int cnt){
push(k,l,r);
if(l>r)return 0;
if(l==r)return t[k]==cnt?dis[num[l]]-dis[f[num[l]]]:0;
int mid=(l+r)>>1;
return max(query(k<<1,l,mid,cnt),query(k<<1|1,mid+1,r,cnt));
}
void add(int k,int l,int r,int x,int y){
if(x>y)return;
if(l==x&&r==y){++t[k];return;}
push(k,l,r);
int mid=(l+r)>>1;
if(mid>=x)add(k<<1,l,mid,x,min(mid,y));
if(mid<y)add(k<<1|1,mid+1,r,max(x,mid+1),y);
}
void clear(int k,int l,int r){
t[k]=0;if(l==r)return;int mid=(l+r)>>1;clear(k<<1,l,mid);clear(k<<1|1,mid+1,r);
}
void add(int x,int y){
for(;bl[x]!=bl[y];){
add(1,1,n,id[bl[y]],id[y]);
y=f[bl[y]];
}
add(1,1,n,id[x]+1,id[y]);
}
bool check(int t){
int mx=0,cnt=0;clear(1,1,n);
for(int i=1;i<=m;++i){
if(t<dist[i])
add(lca[i],x[i]),
add(lca[i],y[i]),
mx=max(mx,dist[i]),++cnt;
}
int ans=-query(1,1,n,cnt);
return mx+ans<=t;
}
int main(){
n=read();m=read();
for(int i=1;i<n;++i){
int x=read(),y=read(),w=read();
ins(x,y,w);ins(y,x,w);
}
dfs1(1);dfs2(1,1);
for(int i=1;i<=m;++i){
x[i]=read(),y[i]=read(),lca[i]=lc(x[i],y[i]);
dist[i]=dis[x[i]]+dis[y[i]]-2*dis[lca[i]];
mx=max(dist[i],mx);
}
int l=0,r=mx;
for(;l<=r;){
int mid=(l+r)>>1;
if(mid==11){
mid=0;
mid=11;
}
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
out(ans);
return 0;
}