# [CF1111E] Tree

Portal

$Dp[i][j] = Dp[i - 1][j - 1] + Dp[i - 1][j] * (j - h[i])$
$h[i]$表示一个点到根的链上有多少个询问点.

#### Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s\n", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
char ch = getchar();
int x = 0, flag = 1;
for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(LL x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar(x % 10 + 48);
}

const int Maxn = 200009, Mod = 1e9 + 7;
struct edge {
int to, nxt;
}g[Maxn << 1];
int fa[Maxn][21], dep[Maxn], Euler_clk, Beg[Maxn], End[Maxn];
void dfsInit(int u, int pa) {
fa[u][0] = pa, dep[u] = dep[pa] + 1;
rep (i, 1, 20) fa[u][i] = fa[fa[u][i - 1]][i - 1];
Beg[u] = ++Euler_clk;
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v != pa) dfsInit(v, u);
}
End[u] = ++Euler_clk;
}

void init() {
rep (i, 1, n - 1) {
}

dfsInit(1, 0);
}

int LCA(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
drep (i, 20, 0)
if (dep[fa[u][i]] >= dep[v]) u = fa[u][i];
if (u == v) return u;
drep (i, 20, 0)
if (fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
return fa[u][0];
}

int dp[309], instack[Maxn];
vector <int> qset, Tmp;
stack <int> s;
vector <pair<int, int> > Fak;

struct Tree {
edge g[Maxn << 1];
int head[Maxn], e, h[Maxn], mark[Maxn], vised[Maxn];
vector <int> ln;
void init() {
if (ln.size() == 0) clar(head, -1);
rep (i, 0, ln.size() - 1)
head[ln[i]] = -1, h[ln[i]] = mark[ln[i]] = vised[ln[i]] = 0;
ln.clear(), e = 0;
}
void add(int u, int v) {
if (!vised[u]) ln.push_back(u), vised[u] = 1;
}
void setMark(int u) { mark[u] = 1; }
int getMark(int u) { return h[u] - mark[u]; }
void travel(int u, int pa) {
h[u] = h[pa] + mark[u];
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v != pa) travel(v, u);
}
}
}lst;
int cmp(int u, int v) {
return (u < 0 ? End[-u] : Beg[u]) < (v < 0 ? End[-v] : Beg[v]);
}

void solve() {
rep (Fake, 1, q) {
qset.clear(), Tmp.clear();
rep (i, 1, k) {
qset.push_back(u), instack[u] = 1;
Tmp.push_back(u);
}
if (!instack[r]) qset.push_back(r), instack[r] = 1;
sort(qset.begin(), qset.end(), cmp);
rep (i, 1, qset.size() - 1) {
int l = LCA(qset[i - 1], qset[i]);
if (!instack[l]) instack[l] = 1, qset.push_back(l);
}
if (!instack[1]) instack[1] = 1, qset.push_back(1);

rep (i, 0, qset.size() - 1) qset.push_back(-qset[i]);
sort(qset.begin(), qset.end(), cmp);

lst.init();
rep (i, 1, k) lst.setMark(Tmp[i - 1]);

while (!s.empty()) s.pop();
rep (i, 0, qset.size() - 1)
if (qset[i] > 0) s.push(qset[i]);
else {
int u = s.top(); s.pop(); instack[u] = 0;
}
qset.clear();
lst.travel(r, 0);

int flag = 0;
rep (i, 1, k) flag |= (lst.getMark(Tmp[i - 1]) >= m);
if (flag) {
puts("0");
continue;
}

rep (j, 0, m) dp[j] = 0;
rep (i, 1, k) {
Fak.push_back(make_pair(lst.getMark(Tmp[i - 1]), Tmp[i - 1]));
//          printf("%d %d\n", lst.getMark(Tmp[i - 1]), Tmp[i - 1]);
}
sort(Fak.begin(), Fak.end());

dp[0] = 1;
rep (j, 1, k)
drep (l, min(j, m), 0)
if (l <= Fak[j - 1].first) dp[l] = 0;
else {
dp[l] = 1ll * dp[l] * (l - Fak[j - 1].first) % Mod;
if (l > 0) dp[l] = (1ll * dp[l] + dp[l - 1]) % Mod;
}

Tmp.clear(), Fak.clear();
LL ans = 0;
rep (i, 1, m) (ans += dp[i]) %= Mod;
printf("%d\n", ans);
}
}

int main() {
freopen("CF1111E.in", "r", stdin);
freopen("CF1111E.out", "w", stdout);

init();
solve();

#ifdef Qrsikno
debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
return 0;
}

posted @ 2019-02-06 22:18 Qrsikno 阅读(...) 评论(...) 编辑 收藏