Codeforce Round 712 Div2

Codeforce Round 712 Div2
A. Deja Vu

题目链接
题目大意:
给定一个字符串,判断能否在这个字符串的某一个位置加入一个字符 ‘a’ 使得该字符串变成非回文串,输出 “YES” 或 “No”。
解题思路:
首先可得全由 a 组成的字符串必然不能满足条件,那么对于不全为 a 的串,若是回文的则可以直接加到字符串头部(反证法若加到头部不满足,那么递推可知该字符串全为 a ),对于非回文的则在开头与末尾各自判断一次,输出可能的结果即可。

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
typedef pair<int, int> PII;
const int N=3e5+10;
int q[N];
char s[N];
typedef long long ll;
int main()
{
    int t;
    cin >> t;
    while(t--){
        memset(s, 0, sizeof s);
        cin >> s + 1;
        int num = 0;
        bool can = 0;
        for (int i = 1; s[i] != '\0';i++){
            num++;
            if(s[i]!='a'){
                can = 1;
            }
        }
        if(!can){
            puts("NO");
            continue;
        }
        bool jug = true;
        for (int i = 1, j = num; i <= j;i++,j--){
            if(s[i]!=s[j]){
                jug = false;
            }
        }
        if(jug){
            puts("Yes");
            printf("a");
            for (int i = 1; s[i] != '\0';i++){
                printf("%c", s[i]);
            }
            printf("\n");
        }
        else{
            s[0] = 'a', s[num+1]='a';
            bool ans1 = 0, ans2 = 0;
            for (int i = 0, j = num; i <= j;i++,j--){
                if(s[i]!=s[j]){
                    ans1 = 1;
                    break;
                }
            }
            for (int i = 1, j = num + 1; i <= j;i++,j--){
                if(s[i]!=s[j]){
                    ans2 = 1;
                    break;
                }
            }
            if(!ans1&&!ans2){
                puts("No");
            }
            else{
                puts("Yes");
                if(ans1){
                    for (int i = 0; i <= num;i++){
                        printf("%c", s[i]);
                    }
                    printf("\n");
                    continue;
                }
                if(ans2){
                    for (int i = 1; i <= num + 1;i++){
                        printf("%c", s[i]);
                    }
                    printf("\n");
                    continue;
                }
            }
        }
    }
    return 0;
}
B.Flip and Bits

题目链接
题目大意:
给定一个01序列 a ,每次可以从左往右,从开头确定一个子串,该字串中 1 的个数等于 0 的个数,将这个子串的 0 变为 1,1 变为 0,试判断 a 串是否可以通过多次这样的操作变为 b 串。
解题思路:
我们可以先确定每个子串的右端点,由于不限定次数,所以符合条件的部分可以随意转换,那么对每一段区间两个串不匹配的点进行枚举,只有当不匹配的点为0或全部时,才可以通过转换进行匹配,遍历一遍即可,注意最长的满足条件的子串的右端点不一定为 a 串的最后一个字符,所以要进行特判。

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
typedef pair<int, int> PII;
const int N=3e5+10;
int q[N];
char a[N], b[N];
typedef long long ll;
int main()
{
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        cin >> a + 1;
        cin >> b + 1;
        int num0 = 0, num1 = 0;
        bool can = 0;
        vector<int> ch;
        ch.push_back(0);
        for (int i = 1; i <= n;i++){
            if(a[i]!=b[i]){
                can = 1;
            }
            if(a[i]=='0'){
                num0++;
            }
            if(a[i]=='1')
                num1++;
            if (num1 == num0)
                ch.push_back(i);
        }
        if(!can){
            puts("YES");
            continue;
        }
        else{
            bool ans = 0;
            if(ch.size()==1){
                puts("NO");
                continue;
            }
            for (int i = 1; i < ch.size();i++){
                int cnt = 0;
                for (int j = ch[i-1]+1; j <= ch[i];j++){
                    if(a[j]!=b[j]){
                        cnt++;
                    }
                }
                if(cnt>0&&cnt<ch[i]-ch[i-1]){
                    ans = 1;
                    break;
                }
            }
            if(ch[ch.size()-1] < n){
                for (int j = ch[ch.size() - 1]+1; j <= n;j++){
                    if(a[j]!=b[j]){
                        ans = 1;
                    }
                }
            }
            if(ans){
                puts("NO");
            }
            else
                puts("YES");
        }
    }
    return 0;
}
C.Balance the Bits

题目链接
给定一个01序列 s 与a, b两个括号序列,s中第 i 位若为 1 那么a, b 的第 i 位相同,反之则不同,判断能否构成合法的括号序列 a, b如果可以,那么输出这样的序列。
解题思路:
易得a, b两个序列的起始位与末位必须是相同的,所以 s 的初末位必须都为 1 ,那么考虑剩下的部分,对于一个合法的括号序列可得左括号与右括号个数应当是相等的。
由于n规定为偶数,那么对于内部的字符,当存在奇数个 1 时,不管怎么选取都无法满足左右括号数目相同,所以 1 的个数应当为偶数。
下面考虑如何输出合法的序列,对于 s 的2位到n-1位,分别统计0,1的个数,如果0的个数为奇数,那么 a 的这一位输出左括号,反之输出右括号,对1也同理,那么可得此时 a 除端点外的内部一定合法,对b来说,最左边的0与最右边的0分别与两个端点的括号匹配,其余0内部匹配,1也可以内部匹配,所以这样分配是合法的。

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
typedef pair<int, int> PII;
const int N=3e5+10;
const int mod = 1e9 + 7;
char s[N];
typedef long long ll;
int main()
{
    int t;
    cin>>t;
    while(t--){
        memset(s, 0, sizeof s);
        int n;
        cin >> n;
        cin >> s + 1;
        int num_0 = 0;
        for (int i = 2;i<=n-1;i++){
            if(s[i]=='0'){
                num_0++;
            }
        }
        if(s[1]!='1'||s[n]!='1'||num_0%2!=0){
            cout << "NO" << endl;
            continue;
        }
        cout << "YES" << endl;
        vector<char> ans;
        ans.push_back('(');
        int num0 = 0, num1 = 0;
        for (int i = 2; i <= n - 1;i++){
            if(s[i]=='0'){
                num0++;
                if(num0&1){
                    ans.push_back('(');
                }
                else
                    ans.push_back(')');
            }
            else{
                num1++;
                if(num1&1){
                    ans.push_back('(');
                }
                else
                    ans.push_back(')');
            }
        }
        ans.push_back(')');
        for (int i = 0; i < ans.size();i++){
            cout << ans[i];
        }
        cout << endl;
        for (int i = 0; i < ans.size();i++){
            if(s[i+1]=='1'){
                cout << ans[i];
            }
            else{
                if(ans[i]=='(')
                    cout << ')';
                    else
                        cout << '(';
            }
        }
        cout << endl;
    }
    return 0;
}
D. 3-coloring

题目链接
题目大意
给定一个n*n的矩阵,有三种颜色可供选择,每次A玩家选定一种颜色,B玩家从剩余的两种颜色里选择一种填在空的格子里,如果有两个相邻的格子的颜色相同,那么B输,反之若填满全部格子且无上述情况B赢,已知B总有办法获胜,下面给定A的每步的选择,输出每一步B选择的颜色与格子。
解题思路
我们先考虑两种颜色的情况,易得若涂成国际象棋盘的形状就是满足条件的,类比到此题,我们可以根据前两个输入来确定棋盘的黑白格对应的颜色。那么优先用对应的颜色来把相应的格子来填满,当出现一种格子已满的时候,那么就填在未满的那种格子里(取不同于已满格子的颜色)。

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
typedef pair<int, int> PII;
const int N=3e5+10;
const int mod = 1e9 + 7;
char s[N];
typedef long long ll;
vector<PII> co1, co2;
int n, p1 = 1, p2 = 1;
int cor1, cor2; //记录黑白格代表的颜色
int find_c(int x){
    if(x == 1){
        return 2;
    }
    else
        return 1;
}
int find_c1(int x, int y){
    if(x==y)
        return find_c(x);
    else{
        if(x > y)
            swap(x, y);
            if(x==1&&y==2)
                return 3;
            if(x==1&&y==3)
                return 2;
            if(x==2&&y==3)
                return 1;
    }
}

void solve(int x){
    if(p1==co1.size()){
        cout << find_c1(x, cor1) << ' ' << co2[p2].first << ' ' << co2[p2].second << endl;
        p2++;
    }
    else if(p2==co2.size()){
        cout << find_c1(x, cor2) << ' ' << co1[p1].first << ' ' << co1[p1].second << endl;
        p1++;
    }
    else{
        if(cor1==x){
            cout << cor2 << ' ' << co2[p2].first << ' ' << co2[p2].second << endl;
            p2++;
        }
        else{
            cout << cor1 << ' ' << co1[p1].first << ' ' << co1[p1].second << endl;
            p1++;
        }
    }
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n;i++){
        for (int j = 1; j <= n;j++){
            if((i+j)%2==0){
                co1.push_back({i, j});
            }
            else{
                co2.push_back({i, j});
            }
        }
    }
    int a;
    cin >> a;
    cor1 = find_c(a);
    cout << cor1 << " 1 1" << endl;
    fflush(stdout);
    cin >> a;
    cor2 = find_c1(cor1, a);
    cout << cor2 << " 1 2" << endl;
    fflush(stdout);

    int t = n * n - 2;
    while(t--){
        int a1;
        cin >> a1;
        solve(a1);
        fflush(stdout);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值