bzoj3648 寝室管理
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3648
【题解】
明天就要去ctsc/apio了有点小激动啊(题解无关
这道题如果是树就是一个裸的点分治+BIT啦!
环套树啊。。去掉环上一条边,点分+BIT算一下。
然后考虑通过这条边,一定是某点环套树-》边-》某点环套树
一遍扫环BIT计算即可。
这样例神坑啊。。少了个2
真正的样例可以看程序最后(答案没错)
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, m, K; int head[M], nxt[M], to[M], tot=1; bool del[M]; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } ll ans = 0; // ================== BIT =================== // namespace BIT { const int M = 6e5 + 10; int c[M], n; # define lb(x) (x&(-x)) inline void init(int _n) { n = _n; memset(c, 0, sizeof c); } inline void edt(int x, int d) { for (; x<=n; x+=lb(x)) c[x] += d; } inline int sum(int x) { int ret = 0; for (; x; x-=lb(x)) ret += c[x]; return ret; } inline int sum(int x, int y) { return sum(y) - sum(x-1); } # undef lb } // ================== dfz =================== // int sz[M], mx[M]; bool vis[M]; inline void getsz(int x, int fa=0) { sz[x] = 1, mx[x] = 0; for (int i=head[x]; i; i=nxt[i]) { if(del[i] || to[i] == fa || vis[to[i]]) continue; getsz(to[i], x); sz[x] += sz[to[i]]; if(sz[to[i]] > mx[x]) mx[x] = sz[to[i]]; } } int mi, centre; inline void getcentre(int x, int tp, int fa=0) { if(sz[tp] - sz[x] > mx[x]) mx[x] = sz[tp] - sz[x]; if(mx[x] < mi) mi = mx[x], centre = x; for (int i=head[x]; i; i=nxt[i]) { if(del[i] || to[i] == fa || vis[to[i]]) continue; getcentre(to[i], tp, x); } } inline void getans(int x, int d, int fa=0) { ans += BIT::sum(max(1, K-d-1), n); for (int i=head[x]; i; i=nxt[i]) { if(del[i] || to[i] == fa || vis[to[i]]) continue; getans(to[i], d+1, x); } } inline void addans(int x, int d, int fa=0) { BIT::edt(d, 1); for (int i=head[x]; i; i=nxt[i]) { if(del[i] || to[i] == fa || vis[to[i]]) continue; addans(to[i], d+1, x); } } inline void delans(int x, int d, int fa=0) { BIT::edt(d, -1); for (int i=head[x]; i; i=nxt[i]) { if(del[i] || to[i] == fa || vis[to[i]]) continue; delans(to[i], d+1, x); } } inline void dfz(int x) { getsz(x); mi = n; getcentre(x, x); x = centre; // do something for (int i=head[x]; i; i=nxt[i]) { if(del[i] || vis[to[i]]) continue; getans(to[i], 1, x); addans(to[i], 1, x); } ans += BIT::sum(K-1, n); for (int i=head[x]; i; i=nxt[i]) { if(del[i] || vis[to[i]]) continue; delans(to[i], 1, x); } vis[x] = 1; for (int i=head[x]; i; i=nxt[i]) { if(del[i] || vis[to[i]]) continue; dfz(to[i]); } } inline void solve_dfz() { memset(vis, 0, sizeof vis); BIT::init(n); dfz(1); } int st[M], stn, c[M], cn; inline void dfs_circle(int x, int fa=0) { if(cn) return; if(vis[x]) { for (int i=stn; st[i]!=x; --i) c[++cn] = st[i]; c[++cn] = x; return ; } st[++stn] = x; vis[x] = 1; for (int i=head[x]; i; i=nxt[i]) { if(to[i] == fa) continue; dfs_circle(to[i], x); } --stn; } int d[M], dn=0; inline void getdis(int x, int dis, int fa=0) { d[++dn] = dis; for (int i=head[x]; i; i=nxt[i]) { if(to[i] == fa || del[i] || vis[to[i]]) continue; getdis(to[i], dis+1, x); } } inline void solve() { stn = cn = 0; dfs_circle(1); // printf("%d\n", cn); // for (int i=1; i<=cn; ++i) printf("%d ", c[i]); // puts(""); for (int i=head[c[1]]; i; i=nxt[i]) { if(to[i] == c[cn]) { del[i] = 1; del[i^1] = 1; break; } } solve_dfz(); // cross c[cn]->c[1] // printf("%lld\n", ans); BIT::init(n); memset(vis, 0, sizeof vis); for (int i=1; i<=cn; ++i) vis[c[i]] = 1; for (int i=1; i<=cn; ++i) { dn = 0; getdis(c[i], 0); for (int j=1; j<=dn; ++j) ans += BIT::sum(max(1, K-(cn-i+1)-d[j]), n); for (int j=1; j<=dn; ++j) BIT::edt(d[j]+i, 1); } printf("%lld\n", ans); } int main() { scanf("%d%d%d", &n, &m, &K); for (int i=1, u, v; i<=m; ++i) { scanf("%d%d", &u, &v); adde(u, v); } if(n == m) solve(); else solve_dfz(), printf("%lld\n", ans); return 0; } /* 5 5 2 1 3 2 4 3 5 4 1 5 2 */