首页 > 其他分享 >P4099 [HEOI2013] SAO

P4099 [HEOI2013] SAO

时间:2023-10-12 20:37:53浏览次数:32  
标签:cnt SAO int siz 合并 head HEOI2013 P4099 1001

P4099 [HEOI2013] SAO

很有意思的一道题。

考虑树形 DP。首先考虑的是 \(f_i\) 表示 \(i\) 为根的子树内合法的拓扑序数量,但是这样合并子树的时候是无法计算的,如下图:

假设 \(1\) 当前合并了 \(3\) 这棵子树,接下来要合并红色和蓝色的部分,此时 \(2\) 必须在 \(1\) 之后挑战,但是方案数并不是简单地两个 \(f\) 值相乘,观察可以发现 \(5,4,7\) 号点的合并顺序是任意的,并且 \(1,2\) 都挑战了之后 \(3,6,8\) 的挑战顺序也不是一种,所以我们合并的时候会乘两个神秘系数。

观察性质,合并 \(i,to\) 两棵树时,问题可以抽象为两个序列,合并之后 \(i\) 需要在 \(to\) 前面并且保持原先相对顺序不变,而上面所说的的神秘系数其实完全由在 \(i,to\) 之前与之后的数的个数决定。

注意到我们并不关心前面的数的顺序,因为这个东西显然满足乘法原理,只需要把顺序数存在 \(f\) 里直接乘起来就是对的。

很自然的,想到再加一维状态 \(f_{i,j}\) 表示 \(i\) 在它当前子树内排名为 \(j\) 的方案数(本质上还是记录的在它之前的数的个数 \(j-1\),而在它之后的数就是 \(siz_i-j\)),接下来是愉快的推式子时间:

设 \(i,to\) 为当前合并的两棵树,其中 \(i\) 在它所在的子树内排在第 \(j\) 位,\(to\) 在它所在的子树内排在第 \(k\) 位。

若 \(i\) 指向 \(to\),即 \(i\) 在 \(to\) 之前挑战,则合并大概是这样的:

橙圈表示合并后的序列在 \(i\) 之前的数字数,枚举 \(t\) 表示合并后 \(i\) 的位置在第 \(t\) 位,则红圈一定是第 \(t\) 个,橙圈中应当有 \(t-1\) 个数,其中 \(j-1\) 个为序列 \(i\) 中的元素,合并顺序随意,所以第一个系数就是 \(C_{t-1}^{j-1}\)。

新序列中第 \(t\) 个为数字是 \(i\),接下来 \(siz_i+siz_to-t\) 个数中有 \(siz_i-j\) 个是序列 \(i\) 中的元素,所以第二个系数就是 \(C_{siz_i+siz_to-t}^{siz_i-j}\)。

对于 \(t\) 的取值,最少取 \(j\),最多取 \(j+k-1\),因为 \(to\) 一定在 \(i\) 之后,如果 \(t>j+k-1\) 则一定是合法。

整理一下,在外层枚举 \(t\),求出 \(k\) 的取值范围 \([1,t-j+1]\) 就得出转移方程:

\[f_{i,t}=f_{i,j}f_{to,k}C_{t-1}^{j-1}C_{siz_i+siz_to-t}^{siz_i-j} \]

观察一下,其中只有 \(f_{to,k}\) 一项中包含 \(k\),并且是连续的一段,显然可以用前缀和优化。

对于 \(to\) 指向 \(i\) 的情况也是同理,转移方程甚至也是一样的,只不过取值变了一些。

最后讨论一下时间复杂度,对于每一条边连接 \(fa_x\) 和 \(x\),它会被计算 \((siz_{fa_x}-siz_x)siz_x\),相当于是把它两边的点互相枚举了一遍,这样每个点对只会合并一次,所以时间复杂度是优秀的 \(\mathcal O(n^2)\)。

本题无论是状态的设计,方程的推导,范围的计算,转移的优化都需要细致的思考,是一道不可多得的好题。

int T,n,cnt,fr[1001],inv[1001],head[1001],to[2001],nex[2001],v[2001],tmp[1001],f[1001][1001],siz[1001];
inline void add(int x,int y,int z){to[++cnt]=y,v[cnt]=z,nex[cnt]=head[x],head[x]=cnt;}
inline int C(int n,int m){return fr[n]*inv[m]%MOD*inv[n-m]%MOD;}
inline int power(int x,int y)
{
	int s=1;
	for(;y;y>>=1,x=x*x%MOD)if(y&1)s=s*x%MOD;
	return s;
}
void dfs(int x,int fa)
{
	siz[x]=1,f[x][1]=1;
	for(int i=head[x];i;i=nex[i])
	{
		if(to[i]==fa)continue;
		dfs(to[i],x),memcpy(tmp,f[x],sizeof(tmp)),memset(f[x],0,sizeof(f[x]));
		if(v[i]==1)
		{
			for(int j=1;j<=siz[x];++j)
			{
				for(int t=j;t<=j+siz[to[i]]-1;++t)
				f[x][t]=(f[x][t]+tmp[j]*((f[to[i]][siz[to[i]]]-f[to[i]][t-j])%MOD+MOD)%MOD*C(t-1,j-1)%MOD*C(siz[x]+siz[to[i]]-t,siz[x]-j))%MOD;
			}
		}
		else
		{
			for(int j=1;j<=siz[x];++j)
			{
				for(int t=j+1;t<=siz[to[i]]+j;++t)
				f[x][t]=(f[x][t]+tmp[j]*f[to[i]][t-j]%MOD*C(t-1,j-1)%MOD*C(siz[x]+siz[to[i]]-t,siz[x]-j))%MOD;
			}
		}
		siz[x]+=siz[to[i]];
	}
	for(int i=2;i<=siz[x];++i)f[x][i]=(f[x][i]+f[x][i-1])%MOD;
}
inline void mian()
{
	fr[0]=inv[0]=1,read(T);int x,y;char ch;
	for(int i=1;i<=1000;++i)fr[i]=fr[i-1]*i%MOD;
	inv[1000]=power(fr[1000],MOD-2);
	for(int i=999;i>=1;--i)inv[i]=inv[i+1]*(i+1)%MOD;
	while(T--)
	{
		read(n),memset(head,0,sizeof(head)),memset(f,0,sizeof(f)),cnt=0;
		for(int i=1;i<n;++i)read(x),ch=getchar(),read(y),++x,++y,add(x,y,ch=='<'),add(y,x,ch=='>');
		dfs(1,0),write(f[1][n],'\n');
	}
}

标签:cnt,SAO,int,siz,合并,head,HEOI2013,P4099,1001
From: https://www.cnblogs.com/WrongAnswer90-home/p/17760467.html

相关文章

  • P4099 [HEOI2013] SAO
    原题今天我刚知道一个很逆天的事:\(DAG\)的拓扑序方案数不可做!!!,目前能做到的最优方法好像是状压我们考虑这题怎么做,对于一个限制,我们关心的是他俩在拓扑序中的相对排名,而这题恰好是一个树形结构,因此我们考虑树形\(dp\)我们设\(dp_{i,j}\)表示以\(i\)为根的子树,\(i\)在拓......
  • BUUCTF Reverse/[NPUCTF2020]你好sao啊
    里面就一个加密函数,分析后发现这是一段变表的base解密,将四个字符替换成三个字符点击查看代码void*__fastcallRxEncode(constchar*a1,inta2){intv3;//[rsp+18h][rbp-38h]intv4;//[rsp+1Ch][rbp-34h]intv5;//[rsp+20h][rbp-30h]intv6;//[rsp+2......
  • [HEOI2013] Segment李超线段树
    RT感觉会模板就差不多了,可用作处理一些线段或直线的问题,转化过来的也可以。比如DP的斜率优化,直线的话只用一个log,线段要两个log。[HEOI2013]Segment模板#include<iostream>usingnamespacestd;constintmod1=39989;constintmod2=1e9;constdoubleesp=1e-9;const......
  • 【智能优化算法】基于黄金莱维引导机制的阿基米德优化算法(MSAOA)求解单目标优化问题
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • CasaOs安装和卸载
    QuickSetupCasaOS一步安装:wget-qO-https://get.casaos.io|sudobashorcurl-fsSLhttps://get.casaos.io|sudobashUninstallCasaOSv0.3.3ornewercasaos-uninstallBeforev0.3.3curl-fsSLhttps://get.icewhale.io/casaos-uninstall.sh|sudobash这......
  • 玩客云刷cosaOS
      玩客云刷casaos图文教程:玩客云刷casaos图文教程相关工具百度云盘链接:https://pan.baidu.com/s/1iICqPAyv6n0wIOh3H3mCHQ?pwd=cez7天翼云盘链接:https://cloud.189.cn/webx/share?code=ameyuiYjmMJj(访问码:j3y8)玩客云armbian固件:https://github.com/hzyitc/armbi......
  • AVS3中的ESAO
    增强样点自适应补偿(EnhancedSampleAdaptiveOffset)是AVS3中新增的环路滤波技术,和SAO相比其更充分的考虑了纹理和边缘方向特征。ESAO是在整帧的层面是对所有像素进行分类,然后对每一类像素分别传输一个偏移量进行偏移补偿,偏移量在[-7,7]之间。亮度像素分类对于亮度像素首先按照两种......
  • 【题解】[HEOI2013]SAO
    题目分析:考虑这是一个树形图,所以就先直接当作树来做。这个题其实就是让我们求解有多少种拓扑序而且题目中边方向的限制其实就是在限制拓扑序的前后,而一般这种题在设计\(......
  • SSAO的优化
    优化前predepth生成深度图,法线根据深度在shader中计算出来,也可以通过渲染生成。生成AO图高斯模糊,横一遍竖一遍根据法线,重新计算AO图在不透明物体渲染的时候,正常采样......
  • 【题解】[HEOI2013]Segment(李超树)
    [HEOI2013]Segment题目分析:是李超线段树的板子题,在这里就稍微提一嘴李超线段树吧。其实李超线段树就是用来解决插入线段,查询\(x=k\)时纵坐标的最大值的。对于李超线......