luogu本地可以过的,但是uoj机子巨慢,而且时限还开1s,过不了,有没有什么可以不把倍增改成树剖就能过的卡常方法?
#include<bits/stdc++.h>
using namespace std;
int n,m;
int lca[300005][20],d[300005],f[300005],ch[300005],res[300005][20];
vector<pair<int,int> >p[300005];
inline void dfs(int now,int fa,int ls){
lca[now][0] = f[now] = fa;d[now] = d[fa]+1;res[now][0] = ls;
for(int i = 1;i<18;i++)lca[now][i] = lca[lca[now][i-1]][i-1],res[now][i] = res[now][i-1]+res[lca[now][i-1]][i-1];
for(int i =0 ;i<p[now].size();i++){
if(p[now][i].first==fa)continue;
dfs(p[now][i].first,now,p[now][i].second);
}return;
}inline pair<int,int> lcaa(int x,int y){
if(d[x]<d[y])swap(x,y);
int dis = abs(d[x]-d[y]),sum =0 ;
for(int i =0;i<18,dis;i++,dis>>=1){
if(dis&1)sum+=res[x][i],x = lca[x][i];
}if(x == y)return {x,sum};
for(int i = 17;i>=0;i--){
if(lca[x][i] != lca[y][i])sum+=res[x][i]+res[y][i],x = lca[x][i],y = lca[y][i];
}return {lca[x][0],sum+res[x][0]+res[y][0]};
}inline pair<int,int> dis(int x,int y){
int l = lcaa(x,y).first;
int dis = abs(d[x]-d[l]);int ans =0;
for(int i =0;i<17,dis;i++,dis>>=1)if(dis&1)ans+=res[x][i],x= lca[x][i];
dis = abs(d[y]-d[l]);
for(int i =0;i<17,dis;i++,dis>>=1)if(dis&1)ans+=res[y][i],y= lca[y][i];
return {l,ans};
}
inline void dfs2(int now){
for(int i =0;i<p[now].size();i++){
if(p[now][i].first == f[now])continue;
dfs2(p[now][i].first);
ch[now]+=ch[p[now][i].first];
}return;
}vector<pair<pair<int,int>,int> >edge;
int mx =0;
struct node{
int x,y,l,sum;
};vector<node>query;
bool check(int x){
//cout << x << endl;
memset(ch,0,sizeof(ch));
int tot = 0,c = 0;
for(int i =0;i<query.size();i++){
if(query[i].sum>x){
// cout << query[i].x << " " << query[i].y << " " << query[i].sum << " " <<query[i].l<< endl;
ch[query[i].x]+=1,ch[query[i].y]+=1;
ch[query[i].l]-=2;
c= max(c,query[i].sum);tot++;
}
}if(mx+x<c)return 0;
//cout << tot << endl;
//for(int i = 1;i<=n;i++)cout << ch[i] << " ";cout << endl;
dfs2(1);
//for(int i =1;i<=n;i++)cout << ch[i] << " ";cout << endl;
for(int i =0;i<edge.size();i++){
int xx = edge[i].first.first,y = edge[i].first.second;
int p = xx;
if(d[xx]<d[y])p= y;
if(ch[p] == tot){
// cout << xx << " " << y << endl;
if(edge[i].second>=c-x)return 1;
}
}return 0;
}
signed main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
cin >> n >> m;
for(int i = 1;i<n;i++){
int a,b,c;cin >> a >> b >> c;
p[a].push_back({b,c}),p[b].push_back({a,c});
edge.push_back({{a,b},c});mx= max(mx,c);
}dfs(1,1,0);
// cout << 0<< endl;
for(int i = 1;i<=m;i++){
int a,b;cin >> a >> b;pair<int,int>e = lcaa(a,b);
query.push_back((node){a,b,e.first,e.second});
}int l = 0,r = 3e8;
while(l<r){
int mid = l+r>>1;
if(check(mid))r = mid;
else l = mid+1;
}cout << l << '\n';
return 0;
}
此处我省略了一个火车头。