NOIP2024模拟赛9 赛后总结

前言

听说把枕头哭湿,晚上可以梦见大海

先说明一下情况。

T2,同样的数据,本地 500ms sxyz: 1.7s

T3,CF 3s 的时限,什么烂机子开 1s

我们都有光明的未来。

我尽量克制住自己的情绪。

B / ABC176F

很智慧的一道题,稍微总结一下。

首先你显然有 dpi,j,k 表示经过 i 次操作,前面剩下一个 j 一个 k 可以得到的最大分数。

暴力转移其实是比较简单的,假设这一次操作除了 j,k 另外三个数是 a,b,c

  • a,b,c 删掉,dpi,j,k=dpi1,j,k+[a=b=c]

  • a,b,c 中的两个和 j,k 中的一个删掉,不妨设我们删的是 a,b,jdpi,c,k=dpi1,j,k+[a=b=j]

  • a,b,c 中的一个和 j,k 删掉,不妨设我们删的是 a,j,kdpi,b,c=dpi1,j,k+[a=j=k]

观察到第一种转移可以看作是全局加 [a=b=c] 可以直接写一个全局增量标记在前面,最后答案直接 ans+add 即可。

至于后面两个,观察到变化的状态只有 O(n) 个。并且变化一定是变大(因为有第一种转移的存在)

故你考虑把所有变化状态暴力取出来,然后维护一些最大值数组即可。

由于你每次只改变了那些会改变的,故总复杂度 O(n2)

很难崩的是,这个题你一旦常数大了一点你就会喜提 TLE 95

My Submission.

C / CF407D

2700 的题,但是感觉又不完全算的上。

题解非常清晰明了,这里懒得讲了,讲一下自己的巨恶心做法。

为了将这个做法优化到 O(n3) 我也是煞费苦心了。

说实话这个做法真的挺难有语言描述的。

首先你考虑维护一个 numi,l,r,表示对于第 i 行,找到最小的 ji,存在一个数 k1,k2[l,r],满足 ai,k1=aj,k2

接着维护一个 nxti,j,表示找到一个最大的 k 使得 ai,[j,k] 中的数互不相同。

有了 nxti,j,我们考虑再维护一个 bi,j,k,表示找到最大的 li,使得对于 x[i,l],nxtx,jk,如果没有满足的,就是 0

有了这三个数组之后,答案应该是非常好维护的。

我们考虑枚举这个长方形的的最上面一行,假设是第 i 行的 [l,r] 这个区间。

答案应该是 min(minj=inumi,l,rnumj,l,ri+1,bi,l,rl+1)×(rl+1)

感觉还是比较好理解的。至于里面的那一坨 min,它有一些性质,你可以考虑打一个后缀最小值,具体细节可以看代码。

里面唯一的难点在于 num 的求法。

观察到 numi,l,r=min(numi,l+1,r,numi,l,r1),除了这两个产生的贡献,剩下的就只有第 l 和第 r 列对 ai,l,ai,r 产生的贡献了。

如下:

for (int len = 1; len <= m; ++len)
{
	for (int l = 1, r = len; r <= m; ++l, ++r)
	{
		for (int k = n; k >= 1; --k)
		{
			if(r != l) num[k][l][r] = min(num[k][l + 1][r], num[k][l][r - 1]);
			num[k][l][r] = min(num[k][l][r], min(bucket[a[k][l]], bucket[a[k][r]]));
			bucket[a[k][l]] = min(bucket[a[k][l]], (short)k);
			bucket[a[k][r]] = min(bucket[a[k][r]], (short)k);
		}
		for (int k = 1; k <= n; ++k) bucket[a[k][l]] = bucket[a[k][r]] = 0x3f3f;
		// for (int i = 1; i <= n; ++i) cout << i << " " << l << " " << r << " " << num[i][l][r] << endl;
	}
}

其实还有一堆细节,可以考虑直接看代码

人傻常数大啊啊啊啊,每次都是这种恶心的做法,还要被卡常,难崩。

D / ARC118E

感觉考试的时候思考方向完全不对,以及第一篇这个形式化题解其实讲的挺清楚的。

我们定义 S 为我们走的路径所对应的点集,T 为所有的障碍的点集,N 为当前已经确定的状态的点集,

题目即求 SNT[ST=0]

在此基础上我们考虑一个容斥。

答案就会变成 STSST(1)|S|

观察到这个一点也不好求,于是我们考虑换一下位置:

SSS(1)|S|×(ST1)

还可以把最后一个循环去掉:

SSS(1)|S|×(|nSN|)!

这个时候应该比较好 DP 了,因为我们本质上只需要知道 |SN|,外面的阶乘就有了,然后记录一下方案数就行了。

故我们定义 dpi,j,k,0/1,0/1,表示当前走到了 (i,j)|SN|=k0/1,0/1 分别表示第 i 行,第 j 列是否已经有障碍了的方案数。(这两个 0/1 主要是来看你当前能不能搞出一个障碍。)

转移可以直接见代码,最后直接乘上容斥系数即可,重点要了解的是这个容斥是怎么来的。

My Submission

后记

因为被我们强大的绍兴一中搞破防了,所以很水。

You slow down time.In your golden hour

posted @   Saltyfish6  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Document
点击右上角即可分享
微信分享提示