2021暑期个人赛4补题 (待补充)
C - Secret Passwords (并查集)
由题意可知,两个字符串只要有一个字符相等那么就算是一样的密码,而且具有传递性:例如 a b ab,由于a = ab,b = ab, 那么a = b. 所以我们的思路由此可以变成将出现过一样字符的字符放在一个连通块中,考虑用并查集维护这样一个集合:
刚开始有0个连通块,当某一个字母出现时,那么连通块的总数加一,也就是说一共可能有26个连通块,每当遍历一个字符串的时候,将这个字符串中出现过的字符所在的连通块都连接在一起,每连接一次,连通块数量减一。则最后ans = 连通块数目。
样例解释:
初始ans = 0 (还没有字符出现)
a 字符a出现,连通块数量加1 当前ans = 1
b 字符b出现,连通块数量加1 当前ans = 2
ab 字符a,b已经出现,不增加新的连通块数目,因为a和b出现在一个字符中,那么将a连通块与b连接在一起,ans -= 1 当前ans = 1
d 字符d出现,连通块数量加1 当前ans = 2
所以答案是2
code
#include <bits/stdc++.h>
using namespace std;
const int N = 27;
int p[N];
bool st[27];
int n, num;
char s[55];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= 26; i ++ ) p[i] = i;
while (n -- )
{
scanf("%s", s);
if (!st[s[0] - 'a' + 1]) {st[s[0] - 'a' + 1] = true, num ++ ;}
for (int i = 1; s[i]; i ++ )
{
if (!st[s[i] - 'a' + 1]) {st[s[i] - 'a' + 1] = true, num ++ ;}
int x = s[i - 1] - 'a' + 1, y = s[i] - 'a' + 1;
x = find(x), y = find(y);
if (x != y) {p[x] = y, num -- ;}
}
}
printf("%d\n", num);
return 0;
}
E - Coprocessor
I - Alternating Current (stack)
模拟一下可知,当某一段有大于等于两个的+或者-时,这一段可以解开。那么我们可以用栈维护序列,当栈顶元素与我要插入的元素一样的时候直接弹出栈顶即可。到最后如果栈不空那么就说明解不开(不空说明有不连续的+或-),为空就解得开。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
stack<char> s;
char str[N];
int main()
{
scanf("%s",str);
for(int i = 0; str[i]; i ++ )
{
if(s.empty()) s.push(str[i]);
else
{
if(str[i] == s.top()) s.pop();
else s.push(str[i]);
}
}
if(s.empty()) puts("YES");
else puts("NO");
return 0;
}