总的来说考得一般般……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)\) 的复杂度求解。