2024.11.26模拟赛

昨天也打了模拟赛。但没补没总结。为什么呢。因为懒。

今天来了之后先犯困了一个坤小时。犯困的那两个半小时属于是连暴力都没法想怎么去写的那种。好不容易慢慢清醒了,又不想写了。随便打了个T3的暴力,又写了个T1的爆搜,结果爆搜炸了。

所以,今天昨天打的都很不怎么样。

结果考完之后,同学都说T3是去年提高组T3,我当时就是一个问号。

昨日作业链接

今日作业链接


Ehhh Ah


T1【成绩】

期望 不会


T2【插旗】

题目大意:

解题思路:

考虑深搜过程。对于一个节点的子树,它的最长链的长度一定会产生贡献(因为搜到最深后还到下一条链,这个长度很重要)。而搜到最后一条链时,它需要从最底端再回溯到子树之外,所以这条链的长度也会产生贡献。贪心地想,为了使得k最小,我们让最短链最后搜到。也就是说,对于一棵子树,它的最长链与最短链的长度会分别产生贡献。

具体咋写?细节有什么?我不道啊,我没写


T3【括号序列加强版】

题目大意:

解题思路:

暴力dp的复杂度是O(n3),而且分拿的很少 这对于我这个蒟蒻来讲非常不友好www 。于是考虑设一维状态fi表示以si结尾的合法子串个数 可恶我本来也向这个方向想了但没想出来

对于fi,一定存在 j<i 使得 fifj 转移而来,使得 [ j+1,i ] 合法;而为了答案不重不漏,那么它一定是由最大的满足条件的 j 转移而来,也就是说fi 一定是从以i结尾、长度最短的合法区间[ j+1,i ]转移而来。用 lsti 记录 j+1,有状态转移方程:

fi=flati1+1

现在考虑怎么求lsti

因为[ lsti,i ]一定是最短的合法区间,那么它一定满足alsti=ai且区间[ lsti+1,i1 ]合法。循环去求就行,若不存在,那么lsti就为0。

代码如下↓

int j=i-1;
while (j>0&&a[i]!=a[j]) j=lst[j]-1;
lst[i]=j;

长得很像KMP求nxt数组的代码。

所以我们坚信它的时间复杂度和KMP的一样,均摊下来是O(n)

代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+5;
int n;
int a[N];
int lst[N];
int f[N];
int ans;

signed main()
{
	scanf("%lld",&n);
	for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
	
	for (int i=1;i<=n;i++)
	{
		int j=i-1;
		while (j>0&&a[i]!=a[j]) j=lst[j]-1;
		if (a[i]==a[j]) 
		{
			lst[i]=j;
			f[i]=f[lst[i]-1]+1;
			ans+=f[i];
		}		
	}
	printf("%lld",ans);
	return 0;
}

Ehhh Ah


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