Educational Codeforces Round 168 (Rated for Div. 2) 赛后总结

比赛链接

赛时提交情况:

CF1997A. Strong Password

赛时思路

首先看到题目可以想到的是,我们要加入的这个字符不能与其相邻字符相同,所以我没有多想就写出了第一份代码:

if(s[0]=='a') cout<<'b';
else cout<<'a';
cout<<s<<endl;

交上之后喜提 WA 1

于是冷静了一会儿仔细观察了一下样例,发现样例中加入的字符都位于两个相同字符中间,因为会打破原来连续的密码从而实现使输入原来的字符需要的时间变长,所以我们只需要跑一遍字符串找到有无连续的相同字符,有的话就插入一个不相同的字符进去,若无则在字符串末尾特判一下。

赛时 AC 代码

#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
#define MAXN 0x3f3f3f3f3f3f3f3f
#define MINN -0x3f3f3f3f3f3f3f3f
#define Trubiacy ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

//const int N=+29;
int n;
string s;

signed main(){
    Trubiacy;
    // int Tracy=1;
    int Tracy; cin>>Tracy;
    while(Tracy--){
        cin>>s;
        bool f=0;
        cout<<s[0];
        for(int i=1;i<s.size();i++){
            if(s[i]==s[i-1]&&!f){ //若存在相邻的相同字符,则将新字符插入其中间。
                if(s[i]=='a') cout<<'b';
                else cout<<'a';
                f=1;
            }
            cout<<s[i];
        }
        if(!f){ //若不存在,则将新字符放在原字符串末尾。
            if(s[s.size()-1]=='a') cout<<'b';
            else cout<<'a';
        }
        cout<<endl;
    }
    return 0;
}

CF1997B. Make Three Regions

赛时思路

首先看到这道题,第一反应就是 DFS 跑连通块,但是经验告诉我 div2 应该不会在 B 题这样出,且我想不到跑完 DFS 之后怎么做,所以还是犹豫了比较长的一段时间。

后来官方发了新的 Announcement :

"The given grid contains at most one region" is the constraint on the input, not the comment on the picture from the statement. (”给出的网格最多包含一个连通区域“ 是对输入的限制,而不是对图片的说明。)

这个时候我才注意到原题中有这个对输入的限制,这个时候我们根据样例可以得出,若网格有如下结构( o 的位置为空),则 o 的位置可以放置障碍。

x.x   .o.
.o.	  x.x

所以我们可以从头到尾跑一遍,若出现上面两种情况,\(ans\) 的值 \(+1\)

赛时 AC 代码

#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
#define MAXN 0x3f3f3f3f3f3f3f3f
#define MINN -0x3f3f3f3f3f3f3f3f
#define Trubiacy ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

const int N=2e5+29;
int n;
char a[N],b[N];

signed main(){
    Trubiacy;
    // int Tracy=1;
    int Tracy; cin>>Tracy;
    while(Tracy--){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int j=1;j<=n;j++){
            cin>>b[j];
        }
        int ans=0;
        for(int i=2;i<n;i++){
            if(a[i]=='.'&&a[i-1]=='x'&&a[i+1]=='x'&&b[i]=='.'&&b[i-1]=='.'&&b[i+1]=='.') ans++;
            if(b[i]=='.'&&b[i-1]=='x'&&b[i+1]=='x'&&a[i]=='.'&&a[i-1]=='.'&&a[i+1]=='.') ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

CF1997C. Even Positions

赛时思路

看到括号匹配我们首先可以想到的就是使用栈模拟,遇到 ( 就将下标入栈,遇到 ) 就出栈,若遇到 _ 且栈非空就出栈(即 _) ),否则下标入栈(即 _( ),但后来考虑到一种情况或许不可以,(_)... 若开头像这样的话,模拟得下划线为 ) 显然是不可以的,于是我又犹豫了好久……

后来发现题面中一直在强调下划线只存在奇数位置处,即不存在我所考虑的这种情况,所以可以大胆使用上面的模拟。

赛时 AC 代码

#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
#define MAXN 0x3f3f3f3f3f3f3f3f
#define MINN -0x3f3f3f3f3f3f3f3f
#define Trubiacy ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

// typedef pair<int,int> pii;
//const int N=+29;
string s;
stack<int> st;

signed main(){
    Trubiacy;
    // int Tracy=1;
    int Tracy; cin>>Tracy;
    while(Tracy--){
        int n;cin>>n;
        cin>>s;
        int ans=0;
        for(int i=0;i<n;i++){
            if(i%2){
                if(s[i]=='(') st.push(i);
                else{
                    ans+=i-st.top();
                    st.pop();
                }
            } 
            else{
                if(st.size()){
                    ans+=i-st.top();
                    st.pop();
                }
                else st.push(i);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

CF1997D. Maximize the Root

赛时思路

可以想到的是,由于子节点的值不能为负,为了使节点的值最大化,我们要使其子树中各节点的权值尽量平衡。

详情见代码注释。

赛时 AC 代码

#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
#define MAXN 0x3f3f3f3f3f3f3f3f
#define MINN -0x3f3f3f3f3f3f3f3f
#define Trubiacy ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

const int N=2e5+29;
vector<int> v[N];
int a[N];

int dfs(int x){
	int minn=MAXN;
	for(auto y:v[x]) minn=min(minn,dfs(y)); //找到 dfs 后权值最小的子节点。
	if(!v[x].size()) return a[x]; //如果该节点是叶节点,返回其本身的值。
	if(x!=1){
        if(minn>a[x]) return a[x]+(minn-a[x]>>1); //若子节点权值比父节点大,将两节点权值平分
        else return minn; //若子节点权值比父节点小,父节点的权值只能取到 minn。
    }
	return a[x]+minn; //若目前节点为根节点,返回该节点的值 + 最小的子节点的值
}

signed main(){
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			v[i].clear(); //多测不清空,OI 一场空
		}
		for(int i=2;i<=n;i++){
			int p;
			cin>>p;
			v[p].push_back(i); //建图
		}
		cout<<dfs(1)<<endl;
	}
	return 0;
}

总结

本来想补一下 E 题的,看了很多题解没看明白决定不为难自己了。

然后就是!!记住打 CF 一定要带眼睛)

这场 div2 是我有史以来第一次赛时通过 D 题,祝贺!!!

直接 +126 分喜提绿名!!

posted @ 2024-08-01 16:26  Trubiacy  阅读(60)  评论(2编辑  收藏  举报