题目1
小红拿到了一个字符串,她想知道这个字符串能否通过重新排列组成"Baidu"字符串?
注:必须大小写完全相同。
共有t组询问。
输入描述
第一行输入一个正整数t,代表询问次数。
接下来的t行,每行输入一个仅包含英文字母的字符串。所有字符串的长度之和保证不超过200000。
输出描述
对于每次询问,输出一行答案。如果可以通过重新排列组成"Baidu",则输出"Yes",否则输出"No"。
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例。
输入
4
Baidu
baidu
Baidu
bbdu
输出
Yes
No
Yes
No
思路:所谓重新排列后可以变成"Baidu"其实就是要求输入的串满足B、a、i、d、u五个字符各有一个,实现方式有很多。
#include<iostream>
#include<string>
using namespace std;
int main(){
int T, count_B, count_a, count_i, count_d, count_u;
string str;
cin >> T;
while(T--){
cin >> str;
count_B = count_a = count_i = count_d = count_u = 1;
for(char ch:str){
switch(ch){
case 'B':-- count_B;
if(count_B < 0){
goto label;
}
break;
case 'a':-- count_a;
if(count_a < 0){
goto label;
}
break;
case 'i':-- count_i;
if(count_i < 0){
goto label;
}
break;
case 'd':-- count_d;
if(count_d < 0){
goto label;
}
break;
case 'u':-- count_u;
if(count_u < 0){
goto label;
}
break;
}
}
label: cout << (count_B + count_a + count_i + count_d + count_u == 0 ? "Yes\n" : "No\n");
}
return 0;
}
题目2
给定一个整数x,请你构造—个仅由'r'、'e'、'd'三种字符组成的字符串,其中回文子串的数量恰好为x。
字符串的长度不得超过10^5。
输入描述
一个正整数x。
1<=x<=10^9
输出描述
输出一个仅由'r'、'e'、'd'三种字符组成的字符串,长度不得超过10^5。有多解时输出任意即可。
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例。
输入
3
输出
red
说明
输出"dd"也可以通过本题
思路:针对说明的讲解--存在3个回文串,d、d、dd。那么这道题要怎么解?最暴力的方式肯定是我们直接按照每个位置三种字符的方式生成串,再去查询串中有多少回文串进行取舍。然而这种方式复杂度非常的高,有没有什么简单的生成方式?
我们需要明确的是,对于一个长度为n的串,当它只由一种字符构成时,它的回文子串数量是最多的。这一点其实挺显而易见的,例如和,没有长度为2的回文串,而rrr存在两个长度为2的回文串,不过它们都是。
现在我们来递推一下,当字符串为r时,其回文子串数量为1;当字符串为rr时,其回文子串数量为两个r的回文子串数量2加上自身1,一共3;我们发现,对于一个长度为i的连续同字符的串例如,他会有个,个,...,1个, 也就是说,我们定义表示长度为i的字符串的最大回文子串数量,则有:
同时,我们只要通过的方式生成串,就可以保证回文串只可能产生在每一个或或区间内。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int maxn = 1e5 + 7;
int palindromeNum[maxn];
int main(){
int x, palindromeLen, *p, generateLen;
char chList[3] = {'r', 'e', 'd'};
const int charMod = 3;
int charIdx = 0;
string palindromeStr = "";
cin >> x;
palindromeNum[1] = 1;
for(palindromeLen = 2; palindromeNum[palindromeLen - 1] <= x; ++ palindromeLen){
palindromeNum[palindromeLen] = palindromeNum[palindromeLen - 1] + palindromeLen;
}
-- palindromeLen;
x -= palindromeNum[palindromeLen - 1];
palindromeStr = palindromeStr + string(palindromeNum[palindromeLen - 1], 'r');
while(x > 0){
p = lower_bound(palindromeNum + 1, palindromeNum + palindromeLen, x);
if(*p > x){
-- p;
}
generateLen = *p;
x -= generateLen;
charIdx = (charIdx + 1) % charMod;
palindromeStr = palindromeStr + string(generateLen, chList[charIdx]);
}
cout << palindromeStr;
return 0;
}
题目3
小红拿到了一棵树,每个节点被染成了红色或者蓝色。小红定义每条边的权值为:
删除这条边时,形成的两个子树的同色连通块数量之差的绝对值。
小红想知道,所有边的权值之和是多少?
输入描述
第一行输入一个整数n,代表节点的数量。
第二行输入一个长度为n且仅由'R'和'B'两种字符组成的字符串。
第i个字符为'R'代表i号节点被染成红色,为'B'则被染成蓝色。
接下来的n-1行,每行输入两个正整数u和v,代表节点u和节点v相连。
输出描述
一个整数,代表所有边的权值之和。
示例
5
R B R R B
1 2
1 3
2 4
3 5
8
输入
5
R B R R B
1 2
1 3
2 4
3 5
8
输出
5
R B R R B
1 2
1 3
2 4
3 5
8
思路:首先我们需要建树,把无根树转成有根树。然后我们直接在书上进行搜索,每个节点维护两个值(RedNum与BlueNum),同时保留全局的GlobalRedNum与GlobalBlueNum,这样另一棵子树的红蓝节点数为GlobalRedNum-RedNum和GlobalBlueNum-BlueNum,直接遍历这棵树就行。
ss
题目4
小红拿到了一棵树,每个节点被染成了红色或者蓝色。小红定义每条边的权值为:删除这条边时,形成的两个子树的同色连通块数量之差的绝对值。
小红想知道,所有边的权值之和是多少?
输入描述
第一行输入一个整数n,代表节点的数量。
第二行输入一个长度为n且仅由'R'和'B'两种字符组成的字符串。
输出描述
思路: