nowcoder 牛客挑战赛73
https://ac.nowcoder.com/acm/contest/76652
D S 老师的虚树
给n点定树T,边
有颜色
对于 点集S,包含点集S的最小连通点集V’对应的树为生成树T’
w(S)=T’中不同颜色边个数
对于 i=1..n
计算 |S|=i的w的期望Exp(w(S)),结果mod 998244353
n 2e5
2s
512mb
我的思路
感觉就是算贡献,对于点为i的 点集合,对于颜色c的所有边来说,如果有横跨 边的两个点,那么贡献1,否则贡献0
那么考虑不跨边更简单,也就是 贡献i,c
=所有情况 - 不跨边
$= \binom{n}{i}-\sum_{blk_j} \binom{blk_j}{i}$ 其中 blk是按照指定颜色切割的块
那么 $ans_i= C\binom{n}{i}-\sum_{blk_j} \binom{blk_j}{i}$,其中C是颜色总个数,blk是所有颜色独立的切割
那么问题来了,每个颜色切割的块数 = 当前颜色边数+1,
所以右侧有 n+C
个 <=2n
, 但是直接计算,对于每个i来说复杂度也是 $O(n)$的,总的复杂度会tle
生成函数我也想过没想过怎么简化
题解
一样的思路
$ans_i=\sum_{j} \binom{sz_j}{i} = [x^i]\sum_{j}(1+x)^{sz_j}$
$a_i=$大小为i的块的个数
$[x^i]\sum_{j}a_j(1+x)^j$
$=\sum_{j}x^j\sum_{i=j}^n\binom{i}{j}a_i$
$=\sum_{j}x^j\sum_{i=j}^n\frac{i!}{j!(i-j)!}a_i$
$=\sum_{j}\frac{x^j}{j!}\sum_{i=j}^n(a_ii!)\frac{1}{(i-j)!}$
所以需要处理的是右侧
$r_j=\sum_{i=j}^n(a_ii!)\frac{1}{(i-j)!}$
$t_j=r_{n-j}=\sum_{i=n-j}^n(a_ii!)\frac{1}{(i-n+j)!}$
令$k=n-i$有$i=n-k$
$=\sum_{k=n-n}^{n-(n-j)}(a_{n-k}(n-k)!)\frac{1}{(j-k)!}$
$=\sum_{k=0}^{j}(a_{n-k}(n-k)!)\frac{1}{(j-k)!}$
即令 $[x^k]f(x)=a_{n-k}(n-k)!$
$[x^k]g(x)=\frac{1}{k!}$
$r_j=t_{n-j}=[x^{n-j}]f * g(x)$
$ans_i= \frac{1}{i!} r_i=\frac{1}{i!} [x^{n-i}]f * g(x)$
E S 老师的礼物
n个节点的树,只给定 每个节点i的最小邻居 ai
你需要判断
- 该树唯一存在 (需要输出具体树)
- 存在多个方案
- 该树不存在
t 2e5组
n 5e5
1s
512mb
我的思路
首先 如果是合法的树,那么 上面的n条边(i-ai) 一定存在重边
如果只存在一条重边且全部连通,那么树唯一,但不一定满足条件(检验一下每个点实际的最小邻居是否满足)
然而这充要吗?
如果给你一个树,你会怎么统计所有点的最小节点呢?
首先是1, 把所有1相连的节点u,令 au=1
情况1: 这些点里包含2
情况2: 这些点里不包含2
1 | 1-2-3: (a1=2,a2=1,a3=2) |
1 | 4-1-3-2 (a1=3,a2=3,a3=1,a4=1) |
上面核心在于 有且只有1条重复边
1 | 1-3-4-2 (a1=3,a2=4,a3=1,a4=2) |
如何评价呢
1 | (a1=3,a2=4,a3=1,a4=2)得到的是 |
然后这里不是 前置,应该是其它连通块中找
而且最终 所有的要连接到一起
而且连接时 是 不能一个块有两个方案,但是可以块a的点 同时连块B和块C
换句话说 链接 发生时,原本两个块不是同一块
那么用二维坐标表示就是
(x(>=y))
放置时,add(点(x,y))
(x(>=y))
查询时,查询所有点(>=y,<=x)
并做并查集操作
这样如果最后不是1个并查集那么 则该树不存在
这样 如果出现了 已经合并的再次合并那么说明 至少2棵树,(注意最多合并n-1次,但中间如果跳过的话,可能无法合成所有该合并的点
问题1,如果可行,这复杂度是 2d segtree + 并查集
问题2,当不满足时,如何在时间复杂度内判断是 不存在 还是 不唯一
题解
先判断不存在:也就是连通性
对所有$a_u\le v,a_v\le u$的$(u,v)$二元组连边
1 | 大根堆 = maxpq{i,并查集标识} |
emmmmmmmmmm 这样做的话 的确复杂度就很小了不会多个log了
我看题解这里 for v(ai)=n...1, for i in ai2i[v]
然后 堆里的 都满足 u >= v(a[i])
, 找堆里a[u] <= i
这样的话 我的第二个问题就解决了,也就是能判断 无方案的情况了
对于第一个问题 就是 无脑线段树
存储时键为u,值为a[u]
所以每次查询 都是query(a[u]~n, <= u)
, 那么线段树维护区间最小值
注意到这样做 单次复杂度最高是O(n)
但如果真的这样 会让 边超过n-1,也就是有效的 查询和合并次数 一定是 <= n-1的,否则 一旦某次 > n-1 那么直接就退出了,而单次最多n, 所以 不会超时
F S 老师的合并
两个树T1,T2分别有n1,n2个节点,
第一个树 根1,节点编号1~n1
第二个树 根n1+1,节点编号n1+1~n1+n2
问有多少个n1+n2点的有根树T满足,对于Ti中 任意两个点
- Ti中有 祖先关系的点 当且仅当 在T中也有祖先关系,
- 在Ti中x的dfs序小于y, 当且仅当 在T中x的序小于y
求满足的树T的个数 mod 998244353
n1,n2 [1,100]
3s
512mb
我的思路
首先T的根一定是1或n1+1,因为如果是其它节点,那么根据第一个 祖先的当且仅当关系,那它们的祖先有1或n1+1必定不对
考虑最简单的图
1 | 1 4 |
当钦定1是根以后,讨论4是否直接和1连,那么有
1 | 4不和1的直接子节点穿插 = 1的子节点个数+1 |
有什么 发现,有什么问题呢
这里 感觉上 点一定是连续的某个点的子节点的一段
问题是
1 | f([4],[2 3]) |
这里 感觉 不如虚拟一个0节点为T的根
那么g([...],[....])
就是 在两组根,内部保持顺序的情况下的方案数
ans=g([1],[n1+1])
如果这个能快速算出,那么似乎就是$O(n^4)$的问题了
1 | g(a[...],b[...]) |
所以这里想的是dp
1 | dp[i][j] = a消耗了前i个b消耗了前j个的方案数 |
也就是 状态转移 总代价是n^4 就ac了
题解
参考
https://www.nowcoder.com/discuss/598273393213923328
总结
D - 虽然主拆解想到了,但是后面的没在草稿纸上展开,展开还是应该能发现是卷积的形式,我也感觉像但就是自己没 去做把下标逆转的操作,这应该是自己就能做出来的题目
E- (u,v) 对于$a_u\le v,a_v\le u$的所有连线 检查连通性 没想到简单的并查集+堆就可以实现!!!!! 后面也是,感觉主体的逻辑想的没问题,但是细节的复杂度还是没卡死,没卡到位。
F - 这对知识要求比D和E小啊, 感觉也比D和E简单,就是个有点小怪的树上DP