A. Strong Password
思路:想要最长的时间,那么肯定就是如果存在前后相同的字母的时候,在中间插入一个不同的字符 ,如果不存在前后相同的字符,直接在最后插入一个和原字符串最后一个字符不同的字符
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
string s;
signed main() {
cin >> t;
while (t--) {
cin >> s;
if(s.size()==1)
{
if(s =="z")
cout<<"za"<<"\n";
else
{
cout<<s+'z'<<"\n";
}
continue;
}
bool modified = false;
for (int i = 1; i < s.size(); i++) {
if (s[i] == s[i - 1]) {
char charToInsert;
if (s[i - 1] != 'z') {
charToInsert = s[i - 1] + 1;
} else {
charToInsert = 'a';
}
s.insert(s.begin() + i, charToInsert);
modified = true;
break;
}
}
if(modified==false)
{
if(s[s.size()-1]!='z')
s+=s[s.size()-1]+1;
else if(s[s.size()-1]=='z')
{
s+='a';
}
}
cout << s << "\n";
}
return 0;
}
B. Make Three Regions
思路:最开始最多只有一个连通区域,我们只需要判断是否存在
x . x 或者 . . . 这种情况的数据,如果存在,则计数的cnt++,最后输出cnt即可
. . . x . x
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a[3][200005];
char s;
signed main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=2;i++)
{
for(int j=1;j<=n;j++)
{
cin>>s;
if(s=='.')
a[i][j]=1;
else
a[i][j]=0;
}
}
int cnt=0;
for(int j=1;j<=n-2;j++)
{
if(a[1][j]==0&&a[1][j+1]==1&&a[1][j+2]==0&&a[2][j]==1&&a[2][j+1]==1&&a[2][j+2]==1)
cnt++;
else if(a[1][j]==1&&a[1][j+1]==1&&a[1][j+2]==1&&a[2][j]==0&&a[2][j+1]==1&&a[2][j+2]==0)
cnt++;
}
cout<<cnt<<"\n";
}
return 0;
}
C. Even Positions
思路:贪心问题,我们用cnt来统计出现的左括号的次数,碰到左括号则cnt++,碰到右括号,则cnt--并且计算与上一个左括号的差值,如果碰到" _ "则需要判断cnt的次数,如果是0,则放置左括号,非0就是右括号
那么我们怎么去记录左括号的位置呢,可以用栈或者队列,我这边用的队列,每经历一个左括号,就将左括号的下标pb进队列里面,然后碰到右括号则计算与队尾的差值,并且将队列里的队尾元素弹出
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
int t;
cin >> t;
while (t--) {
string s;
int n;
cin >> n;
cin >> s;
int sum = 0;
int cntl = 0;
deque<int> q;
for (int i = 0; i < n; i++) {
if (s[i] == '_') {
if (cntl > 0) {
cntl--;
sum += i - q.back();
q.pop_back();
} else {
cntl++;
q.push_back(i);
}
} else if (s[i] == '(') {
cntl++;
q.push_back(i);
} else if (s[i] == ')') {
if (cntl > 0) {
cntl--;
sum += i - q.back();
q.pop_back();
}
}
}
cout << sum << "\n";
}
return 0;
}
D. Maximize the Root
思路:有趣的树上dp问题,我们只需要用一个minn来统计顶点v的最大转移值即可
面对每个子树,我们都有两种情况,如果说我这个顶点v的值要是大于子树的值,那么就不要转移了,否则值会更小,如果小于子树u的值,那么就要加起来除以2
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int f[200005];
int v;
vector<int> G[200005];
void dfs(int v)
{
int minn=0x3f3f3f3f;//表示v的儿子结点的最大转移值
for(int u:G[v])
{
dfs(u);
minn=min(minn,f[u]);
}
if(minn==0x3f3f3f3f)
{
return ;
}
if(v==1)
{
f[1]+=minn;
return ;
}
if(f[v]<minn)
{
f[v]=(f[v]+minn)/2;
}
else
{
f[v]=minn;
}
}
signed main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>f[i];
G[i].clear();
}
for(int i=2;i<=n;i++)
{
cin>>v;
G[v].push_back(i);
}
dfs(1);
cout<<f[1]<<"\n";
}
return 0;
}