大意: 给定树, 多组询问, 每个询问给出一个点集$S$, 给定$m, r$, 求根为$r$时, $S$的划分数, 满足

  • 每个划分大小不超过$m$
  • 每个划分内不存在一个点是另一个点的祖先

设点$x$的祖先包括x的个数为$f[x]$ (不属于集合S的点不计算), 按$f$排序后, 有转移

$$dp[i][j]=dp[i-1][j-1]+(j-f[i]+1)dp[i-1][j]$$

dp[i][j]为前i个, 划分为j组的方案数

所以讨论一下$r$与$1$的位置关系求出f就行了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
//head const int N = 1e5+10;
int n, q;
vector<int> g[N];
int top[N], fa[N], dep[N], son[N];
int L[N], R[N], sz[N]; int calc(int x, int y, int f) {
int pre = 0, lca;
while (top[x]!=top[y]) {
if (dep[top[x]]<dep[top[y]]) swap(x,y);
pre = top[x];
x = fa[pre];
}
if (x==y) lca=x;
else lca=dep[x]<dep[y]?x:y;
if (lca!=f) return 0;
if (fa[pre]==f) return pre;
return son[f];
} void dfs(int x, int f, int d) {
L[x]=++*L,sz[x]=1,fa[x]=f,dep[x]=d;
int mx = -1;
for (int y:g[x]) if (y!=f) {
dfs(y,x,d+1),sz[x]+=sz[y];
if (mx<sz[y]) mx=sz[y],son[x]=y;
}
R[x]=*L;
}
void dfs2(int x, int tf) {
top[x]=tf;
if (son[x]) dfs2(son[x],tf);
for (int y:g[x]) if (y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
int c[N];
void add(int x, int v) {
for (; x<=n; x+=x&-x) c[x]+=v;
}
void update(int l, int r, int v) {
add(l,v),add(r+1,-v);
}
int query(int x) {
int r = 0;
for (; x; x^=x&-x) r+=c[x];
return r;
}
struct _ {
int x,c,f;
} a[N];
int dp[N][322]; int main() {
scanf("%d%d", &n, &q);
REP(i,2,n) {
int u, v;
scanf("%d%d", &u, &v);
g[u].pb(v),g[v].pb(u);
}
dfs(1,0,0),dfs2(1,1);
while (q--) {
int k, m, r;
scanf("%d%d%d", &k, &m, &r);
REP(i,1,k) {
scanf("%d", &a[i].x);
if (a[i].x==r) {update(1,n,1);continue;}
a[i].c = calc(a[i].x,r,a[i].x);
if (!a[i].c) update(L[a[i].x],R[a[i].x],1);
else update(1,n,1),update(L[a[i].c],R[a[i].c],-1);
}
REP(i,1,k) a[i].f = query(L[a[i].x]);
sort(a+1,a+1+k,[](_ a,_ b){return a.f<b.f;});
if (a[k].f<=m) {
dp[0][0] = 1;
REP(i,1,k) REP(j,a[i].f,m) {
dp[i][j] = (dp[i-1][j-1]+(ll)(j-a[i].f+1)*dp[i-1][j])%P;
}
ll ans = 0;
REP(i,a[k].f,m) ans+=dp[k][i];
printf("%d\n", int(ans%P));
REP(i,1,k) REP(j,a[i].f,m) dp[i][j]=0;
}
else puts("0");
REP(i,1,k) {
if (a[i].x==r) update(1,n,-1);
else if (!a[i].c) update(L[a[i].x],R[a[i].x],-1);
else update(1,n,-1),update(L[a[i].c],R[a[i].c],1);
}
}
}

Tree CodeForces - 1111E (树,计数,换根)的更多相关文章

  1. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  2. Codeforces 891D - Sloth(换根 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 换根 dp 好题. 为啥没人做/yiw 首先 \(n\) 为奇数时答案显然为 \(0\),证明显然.接下来我们着重探讨 \(n\) 是偶数 ...

  3. 「BZOJ3083」遥远的国度(树剖换根

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4859  Solved: 1372[Submit][Status][Discu ...

  4. 2018.10.26 NOIP训练 数数树(换根dp)

    传送门 换根dpdpdp傻逼题好像不好码啊. 考虑直接把每一个二进制位拆开处理. 先dfsdfsdfs出每个点到1的异或距离. 然后分类讨论一波: 如果一个点如果当前二进制位到根节点异或距离为1,那么 ...

  5. 2018.12.19 codeforces 1092F. Tree with Maximum Cost(换根dp)

    传送门 sbsbsb树形dpdpdp题. 题意简述:给出一棵边权为1的树,允许选任意一个点vvv为根,求∑i=1ndist(i,v)∗ai\sum_{i=1}^ndist(i,v)*a_i∑i=1n​ ...

  6. Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】

    传送门:http://codeforces.com/contest/1092/problem/F F. Tree with Maximum Cost time limit per test 2 sec ...

  7. Jamie and Tree CodeForces - 916E (换根)

    大意: n节点树, 每个点有权值, 三种操作: 1,换根. 2, lca(u,v)的子树权值全部增加x. 3, 查询子树权值和. 先不考虑换根, 考虑子树x加v的贡献 (1)对fa[x]到根的树链贡献 ...

  8. Codeforces 1092 F Tree with Maximum Cost (换根 + dfs)

    题意: 给你一棵无根树,每个节点有个权值$a_i$,指定一个点u,定义$\displaystyle value = \sum^v a_i*dist(u,v)$,求value的最大值 n,ai<= ...

  9. [模板] dfs序, 树链剖分, 换根

    树链剖分 树链剖分是一种对树的分治, 可以把树上的任意一条链分解为 \(O(\log n)\) 条在dfs序上相邻的子链, 便于数据结构(如线段树)来维护. 另外, 子树在dfs序上也是一个连续的区间 ...

随机推荐

  1. hive 配置参数说明(收藏版)

    问题导读: 如何设置reduce的个数? Hive 默认的数据文件存储路径? Hive 默认的输出文件格式? 是否开启 map/reduce job的并发提交? 所允许的最大的动态分区的个数? hiv ...

  2. 为什么采用4~20mA的电流来传输模拟量?(转)

    源: 为什么采用4~20mA的电流来传输模拟量?

  3. 20145331魏澍琛《网络对抗》Exp6 信息搜集与漏洞扫描

    20145331魏澍琛<网络对抗>Exp6 信息搜集与漏洞扫描 问题回答 1.哪些组织负责DNS,IP的管理? DNS域名服务器:绝大多数在欧洲和北美洲,中国仅拥有镜像服务器. 全球一共有 ...

  4. Cortex-M3基础

    (一)寄存器 1 寄存器组      R0-R12: 通用寄存器 ------------------------------------------------------------------- ...

  5. 奇怪的分式|2014年蓝桥杯B组题解析第六题-fishers

    奇怪的分式 上小学的时候,小明经常自己发明新算法.一次,老师出的题目是: 1/4 乘以 8/5 小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png) 老师刚想批评他,转念 ...

  6. Java filter中的chain.doFilter详解

    转载: 一.chain.doFilter作用 1.一般filter都是一个链,web.xml 里面配置了几个就有几个.一个一个的连在一起 request -> filter1 -> fil ...

  7. js文字转移效果

    这个例子算是有点样子的. 思路: 字符串操作.左框里面先是预设的.点击按钮时截取左框中的字符串的前一个字符到右框里的字符串后面,以此循环.点击按钮时按钮变为灰色,在循环完成后恢复.计数的总数(右边)是 ...

  8. BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路:真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...

  9. UVa 1626 括号序列(矩阵连乘)

    https://vjudge.net/problem/UVA-1626 题意: 输入一个由 "(" . ")" . "[" . " ...

  10. UVa 1605 联合国大楼

    https://vjudge.net/problem/UVA-1605 题意:有n个国家,要求设计一栋楼并为这n个国家划分房间,要求国家的房间必须连通,且每两个国家之间必须有一间房间是相邻的. 思路: ...