题解:CF1929F Sasha and the Wedding Binary Search Tree

题目大意

不多说,题面已经讲的很清楚了。

题目分析

我们可以发现题目给定的不是一个普通的二叉树,而是二叉搜索树。

考虑一个二叉搜索树的性质:

attribute:二叉搜索树的中序遍历序列是一个从小到大的序列。

同时 SGT 也是二叉搜索树的一种(二叉平衡树)。

所以我们考虑类似 SGT 的平衡操作,把平衡树中序遍历,我们会得到一个从小到大的序列。我们以已知值为临界,可以得到若干组区间。具体的例子:

当然这里面是会有空的,而空的 −1-11 会随机出现在各个地方。

因此我们认为如果把 222333 替换为 −1-11,设 C=21C=21C=21,虽然 222333 这一段与 CCC 无关,我们可以发现这是一个固定的区间。

考虑推广方案,我们设这一段可填入值属于区间 [l,r][l,r][l,r],显然化为插板法问题,最终可以通过大组合数计算法可得。

因此我们总结:

题目思路

main 思路

  1. 求逆元用于计算组合数。
  2. 接下来输入,进行 DFS 得到中序序列。
  3. 直接插板计算得到答案。

求组合数思路

注:函数 CyxC^x_yCyx 表示组合数。

假设我们现在要求 CyxC^x_yCyx 的值。

  1. x>y−xx>y-xx>yx,又公式 Cyx=Cyy−xC^x_y=C^{y-x}_yCyx=Cyyx,可优化为 Cyy−xC^{y-x}_yCyyx
  2. 此时逆元派上用场,具体方式如下——
int ans=1;
for(int i=y-x+1;i<=y;i++)ans=1ll*ans*i%mod;
for(int i=1;i<=x;i++)ans=1ll*ans*inv[i]%mod;

至此我们就完成了全部过程。

完结撒花!

接下来是大家期待的 AC 代码

#include<bits/stdc++.h>
#define NaOH(x,y) (C((x)+(y)-1,(y)-1)%mod)
using namespace std;
typedef long long ll;
const int MAXN=5e5,mod=998244353;
int n,CC;
int lson[MAXN+1],rson[MAXN+1],val[MAXN+1],inv[MAXN+1];
vector<int>order;
void init(void){
	inv[1]=1;
	for(int i=2;i<=MAXN;++i){
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	}
	return;
}
void DFS(int u){
	if(u==-1)return;
	DFS(lson[u]);
	order.push_back(val[u]);
	DFS(rson[u]);
	return;
}
int C(int x,int y){
	if(x<y||y<0)return 0;
	if(y>x-y)return C(x,x-y);
	int t=1;
	for(int i=x-y+1;i<=x;i++)t=1ll*t*i%mod;
	for(int i=1;i<=y;i++)t=1ll*t*inv[i]%mod;
	return t;
}
void solve(void){
	order.resize(1);
	scanf("%d%d",&n,&CC);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",lson+i,rson+i,val+i);
	}
	DFS(1);
	int lst,ans;
	lst=ans=1;
	int d=1;
	for(int i=1;i<=n;i++){
		if(order[i]!=-1){
			ans=1ll*ans*NaOH(i-lst,order[i]-d+1)%mod;
			d=order[i];lst=i+1;
		}
	}
	ans=1ll*ans*NaOH(n+1-lst,CC-d+1)%mod;
	printf("%d\n",ans);
	return;
}
int main(){
	init();
	int T;scanf("%d",&T);
	while(T--)solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值