[ABC394] 记录
[ABC394A] 22222
遍历字符串把所有 2 输出即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
int main(){
cin>>s;
ll l=s.length();
for(int i=0;i<l;i++)
if(s[i]=='2') cout<<2;
cout<<endl;
return 0;
}
[ABC394B] cat
自定义 comp 按字符串长度排序字符串,然后按顺序输出即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
string s[60];
bool comp(string s1,string s2){
return s1.length()<s2.length();
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
sort(s+1,s+n+1,comp);
for(int i=1;i<=n;i++) cout<<s[i];
cout<<endl;
return 0;
}
[ABC394C] Debug
每次改完都遍历必定超时。
设目前正在检测的位置是第 \(i\) 个字符。考虑每次修改只有两种情况:
- 没有产生新的目标,此时需要往后找,继续判断第 \(i+1\) 个字符。
- 修改后因为修改产生了新的目标,此时需要往前找。因为因其只会影响第 \(i-1\) 个字符,所以只需要往前跳一个就可以了。
可以证明对于每个检测,其最多影响一次前面的字符。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
string s;
int main(){
cin>>s;
n=s.length();
for(int i=0;i+1<n;i++){
if(s[i]=='W'&&s[i+1]=='A'){
s[i]='A';
s[i+1]='C';
if(i>0&&s[i-1]=='W'){
i-=2;
}
}
}
cout<<s<<endl;
return 0;
}
[ABC394D] Colorful Bracket Sequence
csp2023 T2 消消乐的超级弱化版。
建立一个栈,从左到右依次判断:如果与栈顶元素相同,那么栈顶元素出栈,当前元素不进栈。(即进行一次消除)否则入栈。最后看一下栈是否为空,为空则代表可以消除。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll l,tot;
char c[200010];
string s;
int main(){
cin>>s;
l=s.length();
for(int i=0;i<l;i++){
if(tot==0) c[++tot]=s[i];
else if(c[tot]=='('&&s[i]==')') tot--;
else if(c[tot]=='['&&s[i]==']') tot--;
else if(c[tot]=='<'&&s[i]=='>') tot--;
else c[++tot]=s[i];
}
if(tot==0) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
[ABC394E] Palindromic Shortest Path
直接从两端中的任意位置开始都不好做。
考虑从中间字符开始。对于一个从点 \(u\) 到点 \(v\) 的长度为 \(l\) 的回文路径,只要存在一个到点 \(u\) 有一条边的点 \(i\),和点 \(v\) 可到达的点 \(j\),且边 \((i,u)\) 和边 \((v,j)\) 的字母相同,那么点 \(u\) 到点 \(v\) 存在长度为 \(l+2\) 的回文路径。
既然这样,那么我们可以用广度优先搜索:记录 \((i,i)\) 为从点 \(i\) 到点 \(j\) 的路径的状态,先把所有的可能的长度为 \(0\) 的回文路径入队(即形为 \((i,i)\) 的状态),再把所有的可能的长度为 \(1\) 的回文路径入队(即形为 \((i,j)\),并且 \(i\) 与 \(j\) 不相等(避免反复入队),且点 \(i\) 到点 \(j\) 有一条边的状态),然后按照上面的模式,用类似 SPFA 的思想,仅在更新了更小的值的时候入队。(由于广度优先搜索的特性,可以保证每个状态只会入队一次)
该算法的正确性可以证明。由于每个状态只会入队一次,每个状态的更新为 \(O(N^2)\),总共有 \(N^2\) 个状态,因此复杂度为 \(O(N^4)\),可以通过本题。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
char s[110][110];
ll ans[110][110];
queue< pair<ll,ll> > q;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans[i][j]=1e18;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>s[i][j];
for(int i=1;i<=n;i++){
ans[i][i]=0;
q.push({i,i});
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j||s[i][j]=='-') continue;
q.push({i,j});
ans[i][j]=1;
}
}
while(!q.empty()){
ll beg=q.front().first;
ll end=q.front().second;
q.pop();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(s[i][beg]=='-'||s[end][j]=='-') continue;
if(s[i][beg]!=s[end][j]) continue;
if(vis[i][j]) continue;
if(ans[beg][end]+2<ans[i][j]){
ans[i][j]=ans[beg][end]+2;
q.push({i,j});
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cout<<(1e18-ans[i][j]>0?ans[i][j]:-1)<<" ";
cout<<endl;
}
return 0;
}
[ABC394F] Alkane
这样的一颗子图,要么是叶子结点,要么是有 \(4\) 个节点连着的节点。
对于一个节点,如果这个节点在子图当中,并且不是叶子结点,那么遍历到这个节点的时候,要么其连接了四个子节点的分支,要么其连接了三个子节点的分支和一个父节点的分支。对于连接了三个子节点的分支和一个父节点的分支的节点,如果父节点并非叶子结点,那么该子图会在父节点被统计。因此只需要统计图中的非叶子节点其连接了四个子节点的分支的情况,和其连接了三个子节点的分支和一个父节点的分支,且父节点是叶子结点的情况,就可以覆盖所有子图。
考虑通过树形 DP 来解决。如果子节点的数量小于 \(4\),那么只能做叶子结点,其对上方节点的贡献是 \(1\);否则其对上方节点的贡献是该节点贡献最大的三个子节点的贡献之和加一。如果子节点的数量大于等于 \(4\),枚举这个节点所有子节点的贡献,统计以下两种情况:
- 图中的非叶子节点其连接了四个子节点的分支的情况——此时该子图的节点数为该节点贡献最大的四个子节点的贡献之和加一。
- 和其连接了三个子节点的分支和一个父节点的分支,且父节点是叶子结点的情况——此时该子图的节点数为该节点贡献最大的三个子节点的贡献之和加二。
在 DP 过程中得到最大值输出即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,maxsum3[200010],ans=-1,u,v;
vector<ll> E[200010];
priority_queue<ll> maxnum[200010];
void dfs(int p,int fa){
int sz=E[p].size();
for(int i=0;i<sz;i++){
int nxt=E[p][i];
if(nxt==fa) continue;
dfs(nxt,p);
maxnum[p].push(maxsum3[nxt]);
}
maxsum3[p]=1;
if(E[p].size()>=4){
for(int i=1;i<=3;i++){
maxsum3[p]+=maxnum[p].top();
maxnum[p].pop();
}
if(maxnum[p].size()>0){
ll tmp=maxsum3[p]+maxnum[p].top();
ans=max(tmp,ans);
}else if(p!=1) ans=max(maxsum3[p]+1,ans);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<n;i++){
cin>>u>>v;
E[u].push_back(v);
E[v].push_back(u);
}
dfs(1,0);
cout<<ans<<endl;
}