統計在一個root下的兩個子樹,每個子樹都和前面的運算一下再加進去對于這種需要排序的運算很麻煩,所以考慮先不去同子樹內點對的算出合法點對個數,然后減去每一棵子樹內的合法點對(它們實際上是不合法的,相當于一個容斥)
算點對用排序+雙指針即可
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1000005;
int n,m,h[N],cnt,rt,sz,si[N],mx[N];
long long dis[N],a[N],tot,ans;
bool v[N];
struct qwe
{int ne,to,va;
}e[N];
int read()
{int r=0,f=1;char p=getchar();while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}
void add(int u,int v,int w)
{cnt++;e[cnt].ne=h[u];e[cnt].to=v;e[cnt].va=w;h[u]=cnt;
}
void gtrt(int u,int fa)
{si[u]=1;mx[u]=0;for(int i=h[u];i;i=e[i].ne)if(e[i].to!=fa&&!v[e[i].to]){gtrt(e[i].to,u);si[u]+=si[e[i].to];mx[u]=max(mx[u],si[e[i].to]);}mx[u]=max(mx[u],sz-si[u]);if(mx[u]<mx[rt])rt=u;
}
void gtde(int u,int fa)
{a[++tot]=dis[u];for(int i=h[u];i;i=e[i].ne)if(e[i].to!=fa&&!v[e[i].to]){dis[e[i].to]=dis[u]+e[i].va;gtde(e[i].to,u);}
}
long long clc(int u)
{tot=0;gtde(u,0);int re=0,l=1,r=tot;sort(a+1,a+tot+1);while(l<r){while(l<r&&a[l]+a[r]>m) r--;re+=r-l,l++;}return re;
}
void wk(int u)
{v[u]=1;dis[u]=0;ans+=clc(u);for(int i=h[u];i;i=e[i].ne)if(!v[e[i].to]){dis[e[i].to]=e[i].va;ans-=clc(e[i].to);sz=si[e[i].to],rt=0;gtrt(e[i].to,0);wk(rt);}
}
int main()
{n=read(),m=read();for(int i=1;i<n;i++){int x=read(),y=read(),z=read();add(x,y,z),add(y,x,z);}m=read();sz=mx[0]=n;gtrt(1,0);wk(rt);printf("%lld\n",ans);return 0;
}
轉載于:https://www.cnblogs.com/lokiii/p/10105488.html
總結
以上是生活随笔為你收集整理的bzoj 3365: [Usaco2004 Feb]Distance Statistics 路程统计【容斥原理+点分治】的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。