【BZOJ 1468】Tree 点分治
点分治$O(nlogn)$
坚持到月考结束后新校就剩下我一个OIer,其他人早已停课了,老师估计懒得为我一个人开机房门,让我跟班主任说了一声,今晚就回到了老校,开始了自己都没有想到会来的这么早的停课生活。
所以先水一道点分治
#include<cstdio> #include<algorithm> #define read(x) x=getint() #define N 40003 #define max(a,b) (a)>(b)?(a):(b) using namespace std; inline int getint() { char c; int fh=1, k=0; for( ; c < '0' || c > '9'; c=getchar()) if ( c == '-') fh = -1; for( ; c >= '0' && c <= '9'; c=getchar()) k = k * 10 + c - '0'; return k * fh; } struct node { int nxt, to, w; } E[N << 1]; bool vis[N]; int root, rtm = N, n, K, cnt = 0, sz[N], di[N], tb[N], tn, ans = 0, point[N]; inline void ins( int x, int y, int z) {cnt++; E[cnt].nxt = point[x]; E[cnt].to = y; E[cnt].w = z; point[x] = cnt;} inline void fdrt( int x, int fa, int s) { sz[x] = 1; int ma=0; for( int tmp = point[x]; tmp; tmp = E[tmp].nxt) if ( !vis[E[tmp].to] && E[tmp].to != fa) { fdrt( E[tmp].to, x, s); sz[x] += sz[E[tmp].to]; ma = max( ma, sz[E[tmp].to]); } ma = max( ma, s - ma); if ( ma < rtm) { rtm = ma; root = x; } } inline void mktb( int x, int fa) { tb[++tn] = di[x]; for( int tmp = point[x]; tmp; tmp = E[tmp].nxt) if ( !vis[E[tmp].to] && E[tmp].to != fa) { di[E[tmp].to] = di[x] + E[tmp].w; mktb( E[tmp].to, x); } } inline int work( int x, int la) { di[x] = la; tn = 0; mktb( x, -1); sort( tb + 1, tb + tn + 1); int head = 1, tail = tn, an = 0; while ( head < tail) { while ( head < tail && tb[head] + tb[tail] > K) --tail; an += tail - head; ++head; } return an; } inline void dfs( int x, int s) { vis[x] = 1; ans += work( x, 0); for( int tmp = point[x]; tmp; tmp = E[tmp].nxt) if ( !vis[E[tmp].to]) { ans -= work( E[tmp].to, E[tmp].w); rtm = N; int ss = sz[x] > sz[E[tmp].to] ? sz[E[tmp].to] : s - sz[x]; fdrt( E[tmp].to, x, ss); dfs( root, ss); } } int main() { read(n); int u, v, e; for( int i = 1; i < n; ++i) { read(u); read(v); read(e); ins( u, v, e); ins( v, u, e); } read(K); fdrt( 1, -1, n); dfs( root, n); printf( "%d\n", ans); return 0; }
第一次交我忘了sort了,,,
NOI 2017 Bless All