bzoj 3365: [Usaco2004 Feb]Distance Statistics 路程統計【容斥原理+點分治】
阿新 • • 發佈:2018-12-12
const pac con 分治 原理 std usaco while ati
統計在一個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; }
bzoj 3365: [Usaco2004 Feb]Distance Statistics 路程統計【容斥原理+點分治】