Codeforces Round #771B - D

题目链接

B. Odd Swap Sort

题意:
相邻数字和为奇数可交换,问是否能不严格升序排列
思路:
不难得出只有相邻数奇偶性不同时才可交换,所以只用考虑单独的奇数和偶数,即奇数和偶数不能降序排列,否则必然要经历一次同奇偶的交换操作,不满足题意
代码:

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const int N = 1e5 + 10;
int n;
int a[N];
void solve(){
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    bool ok = true;
    int odd = 0, even = 0;
    for (int i = 1; i <= n; i ++){
        if (a[i] & 1){
            if (odd > a[i]){
                ok = false;
                break;
            }
            odd = a[i];
        }
        else{
            if (even > a[i]){
                ok = false;
                break;
            }
            even = a[i];
        }
    }
    if (ok) cout << "Yes" << endl;
    else cout << "No" << endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--){
        solve();
    }
    return 0;
}

C. Inversion Graph

题意:
对于数组中i < j且a[i] > a[j], 连一条边,问最终数组有多少联通块
思路:
单调栈,对于单调栈的每一个元素都代表一个联通块,他所代表的是当前联通块的最大值
如果当前数比栈顶大,说明需要添加一个新的联通块,入栈
如果比栈顶小,则从栈中除栈顶外的数,找到比当前数大的值,出栈,因为当前数可以当做联通块之间的边,之前的联通块就可以去掉。
代码:

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const int N = 1e5 + 10;
int n;
void solve(){
    cin >> n;
    stack<int> s;
    for (int i = 1; i <= n; i ++){
        int x;
        cin >> x;
        if (!s.size() ||x > s.top()) s.push(x);
        else {
            int t = s.top();
            while (s.size() && s.top() > x) s.pop();
            s.push(t);
        }
    }
    cout << s.size() << endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--){
        solve();
    }
    return 0;
}

D. Big Brush

题意:
在n * m的网格中,每次使用刷子可以填充2 * 2的格子相同颜色,给定最终成果,是否能在n*m步填充该网格,求解步骤。
思路:
将正向涂色转化为反向消去颜色,图中一定存在一个最后一步2 * 2 的相同颜色方格,以此为起点向四周bfs,此题标记过的格子视为任意颜色,因为消去颜色,标记的格子最终都会被覆盖。

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int, int> PII;
typedef pair<PII, int> PIII;
typedef long long ll;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const int N = 1010;
int n, m;
int c[N][N];
bool st[N][N];
queue<PII> q;
vector<PIII> ans;
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0}, dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
int check(int sx, int sy){
    int nowc = 0;
    if (!st[sx][sy]) nowc = c[sx][sy];
    for (int i = 3; i < 6; i ++){
        int x = sx + dx[i], y = sy + dy[i];
        if (x < 1 || x > n || y < 1 || y > m) continue;
        if (st[x][y]) continue;
        if (!nowc || nowc == c[x][y]) nowc = c[x][y];
        else return 0;
    }
    return nowc;
}
void bfs(){
    while (q.size()){
        auto t = q.front();
        q.pop();
        int sx = t.fi, sy = t.se;
        for (int i = 0; i < 8; i ++){
            int x = sx + dx[i], y = sy + dy[i];
            if (x < 1 || x >= n || y < 1 || y >= m) continue; //不能到达最下或最左
            int nowc = check(x, y);
            if (!nowc) continue;
            //cout << x << ' ' << y << ' ' << nowc << endl;
            ans.pb({{x, y}, nowc});
            st[x][y] = true;
            st[x + 1][y] = true;
            st[x][y + 1] = true;
            st[x + 1][y + 1] = true;
            q.push({x, y});
        }
    }
}
void solve(){
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            cin >> c[i][j];
    
    for (int i = 1; i < n; i ++){
        for (int j = 1; j < m; j ++){
            if (c[i][j] == c[i + 1][j] && c[i][j] == c[i][j + 1] && c[i][j] == c[i + 1][j + 1]){
                q.push({i, j});
                ans.pb({{i, j}, c[i][j]});
                st[i][j] = true;
                st[i + 1][j] = true;
                st[i][j + 1] = true;
                st[i + 1][j + 1] = true;
                //cout << i << ' ' << j << endl;
            }
        }
    }
    bfs();
    bool ok = true;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            if (!st[i][j]) ok = false;
    if (ok){
        cout << ans.size() << endl;
        for (int i = ans.size() - 1; i >= 0; i --)
            cout << ans[i].fi.fi << ' ' << ans[i].fi.se << ' ' << ans[i].se << endl;
    }
    else cout << "-1" << endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T = 1;
    while (T--){
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值