BZOJ 1468 Tree(点分治+双指针 模板题)
Description
给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K
Input
N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k
Output
一行,有多少对点之间的距离小于等于k
Sample Input
7
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10
Sample Output
5
Hint
Source
LTC男人八题系列
题解:模板题,点分治+双指针
#include <bits/stdc++.h> #define IO_read ios::sync_with_stdio(false);cin.tie(0) #define fre freopen("in.txt", "r", stdin) #define _for(i,a,b) for(int i=a; i< b; i++) #define _rep(i,a,b) for(int i=a; i<=b; i++) #define inf 0x3f3f3f3f #define lowbit(a) ((a)&-(a)) using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0'; if(op) x=-x; } template <class T> void write(T x) { if(x<0) putchar('-'), x=-x; if(x>=10) write(x/10); putchar('0'+x%10); } const int maxn=5e4+5; int head[maxn], tot; struct Edge{ int to, next, val; }edge[maxn*2]; void addedge(int u, int v, int w) { edge[++tot]={v, head[u], w}; head[u]=tot; } int n, k; ll ans; int sz[maxn], vis[maxn], max_son, rt, Size; ll dis[maxn], q[maxn]; int l, r; void get_rt(int u, int fa) { sz[u]=1; int num=0; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(vis[v] || v==fa) continue; get_rt(v, u); sz[u]+=sz[v]; num=max(num, sz[v]); } num=max(num, Size-sz[u]); if(num<max_son) max_son=num, rt=u; } void get_dis(int u, int fa) { q[++r]=dis[u]; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to, w=edge[i].val; if(vis[v] || v==fa) continue; dis[v]=dis[u]+w; get_dis(v, u); } } ll solve(int u, int val) { l=1, r=0, dis[u]=val; get_dis(u, 0); ll res=0; sort(q+1, q+r+1); while(l<r) //双指针 { if(q[l]+q[r]<=k) res+=r-l, ++l; else --r; } return res; } void divide(int u) { ans+=solve(u, 0); vis[u]=true; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to, w=edge[i].val; if(vis[v]) continue; ans-=solve(v, w); //容斥 Size=sz[v], max_son=inf; get_rt(v, 0); divide(rt); } } int main() { IO_read; //fre; cin>>n; memset(head, -1, sizeof(head)); for(int i=1,u,v,w; i<n; i++) { cin>>u>>v>>w; addedge(u, v, w), addedge(v, u, w); } cin>>k; Size=n, max_son=inf; get_rt(1, 0); divide(rt); cout<<ans<<"\n"; }