总的来说考得一般般……100+10+85+10,就那样。

T1 a

题意:

给定一个长度为 \(N(N\le 10^7)\) 的仅包含小写字母的字符串。请你求出其字典序最大的子序列。

解法

题解是什么不重要,反正我的玄学方法能过就行了。我的做法是先把所有的字符z找出来输出,再找y,依次下去,然而这个带常数的做法目前为止还是最优解

#include<cstdio>
//#define zczc
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
    wh*=f;return;
}

int m,sum[30];
char w;

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);
	w=getchar();
	while(w<'a'||w>'z')w=getchar();
	sum[w-'a']++;
	for(int i=2;i<=m;i++){
		w=getchar();
		sum[w-'a']++;
		for(int j=w-'a'-1;j>=0;j--)sum[j]=0;
	}
	for(int i=25;i>=0;i--){
		while(sum[i]--)putchar(i+'a');
	}
	
	return 0;
}

T2 b

题意

给定一个长度为 \(N(N\le 5\times 10^6)\) 的序列。删除其中的一个元素需要花费的代价是其本身乘上与其相邻的
元素的乘积。请你求出将该序列删空的最小代价。

解法

首先我想到的是什么区间DP,但是没写出来;后来想到一个似乎是绝妙的优化,那就是每次删除只会删除左端点或者右端点,这样一定是最优的,因为这样一来,每次的代价就会是两个数相乘,而不是三个数连乘。

于是考试时打了个奇怪的线性DP,交上去,只有20分,实在不应该。

后来看了解法,发现是因为没有考虑到一些情况,比如对于序列 1 2 1,它的最优解就是先删中间再删两边,答案为4 。为什么会造成这一情况呢,不是因为结论有问题,而是因为那个“两数乘积小于三数乘积”的结论在这三个数中有1时不再适用。于是用题解的话说,就是以1为分界把原序列割裂成许多小段,对每个小段用上面的结论快速求解。

由数据规模可知,对于每个小段应用 \(O(N)\) 的复杂度求解。

一如既往,万事胜意