题解
T1 蔡老板与公司
70pts
维护所有区间的左边,维护一个栈,如果当前元素和栈顶元素一样,可以配对消掉,否则放到栈顶。
时间复杂度: O ( n 2 ) O(n^2) O(n2)
代码:
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
typedef long long ll;
char s[N],sta[N];
ll sum=0,b[N];
int len;
ll check(int x)
{
int tot=0,ans=0;
for(int i=x;i<len;i++)
{
if(s[i]==sta[tot])tot--;
else sta[++tot]=s[i];
if(tot==0)ans++;
}
return ans;
}
int main()
{
scanf("%s",s);
len=strlen(s);
for(int i=0;i<len;i++)
sum+=check(i);
cout<<sum;
}
100pts
1.hash(可能会被卡)
2.trie字典树。
sum[now] 表示某一时刻位置为now的字符后面有多少相邻的符合条件的字符串被消去,举个例子:
daacbbcbb 对于字符d 后面有三个相邻的符合条件的字符 分别是aa aacbbc aacbbcbb
从根向下把每个字符插入,和70pts思路差不多:
对于当前的字符,若上一个字符与它相同,就把这两个字符都消去,并跳到上上个字符的位置
ans+=sum[now] sum[now]++
一个很丑的示意图QWQ:
对于上面那个序列,蓝色的表示sum的值,黄色表示找到相同的了向上跳,跳了之后sum就++ 所以有些点 sum从1变为2,字符串下面蓝色的数字就代表编号tot.
代码如下:
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
typedef long long ll;
char s[N],str[N];
int ch[N][27],sum[N],fa[N],len,tot=0,now=0;
ll ans=0;
int main()
{
scanf("%s",s+1);
len=strlen(s+1);
sum[0]=1;
for(int i=1;i<=len;i++)
{
if(s[i]!=str[now])
{
if(!ch[now][s[i]-'a'])
{
ch[now][s[i]-'a']=++tot;
str[tot]=s[i];
fa[tot]=now;
}
now=ch[now][s[i]-'a'];
}
else now=fa[now];
ans+=sum[now];
sum[now]++;
}
cout<<ans;
}
T2 蔡老板与豪宅
这道题首先要了解卷积(听起来复杂其实很简单),熟练状压DP,理解容斥原理,然后学会FFT(快速傅里叶变换),学会FMT emmm
I have a dream 今天学会FFT及其代码实现,之后再写一篇博客。
来自大佬的分析:
至于代码先咕一下,等我学会FMT了就贴上来ORZ
T3 蔡老板与宝藏
100pt
就是构造两个环,并在上面进行合并和拆分操作,具体见大佬题解,讲得非常详细。说实话这种构造很巧妙,但实现有点复杂。有一点点没搞懂awsl…
今日总结
1.第一题本以为写出了正解,结果题意理解有点出入导致只有10分。而这题的70分暴力也非常好写, O ( n 2 ) O(n^2) O(n2)轻轻松松就过了,还是挺遗憾的。加了trie树就立马改出正解了
2.第三题确实没什么思路,拿了暴力10分。
3.发现做题多真的有好处,没自己写过的算法听大佬思路会一知半解,但之前了解过有关算法和思路就会很快的明白,并且和之前的知识融会贯通。
4.学信奥任重而道远√