0
点赞
收藏
分享

微信扫一扫

Codeforces Round #771 (Div. 2) ABCD|E

AbrahamW 2022-02-16 阅读 26

A.Reverse

思路

给出一个 [ 1 , n ] [1, n] [1,n]的排列, 要求翻转一次区间,使字典序最小。一次操作字典序最小,那么操作后从头开始的顺序序列长度应该 + 1 +1 +1

那么显然是找到第一个错位的位置,该位置当前点数字一定大于其坐标(证明略)。然后将该位置上应该放置的数字位置找到,区间反转即可,这样可以保证顺序序列增加一个数字,使字典序最小。

Accepted Code

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 600;
int a[N];

inline void solve(){
    int n = 0; cin >> n;
    int minpos = 0, maxpos = 0, minn = 10000000, maxx = 0;
    for(int i = 1; i <= n; i++) cin >> a[i];
    int l = 0, r = 0;
    for(int i = 1; i <= n; i++){
        if(!l){ if(a[i] != i) l = i; }
        else{ if(a[i] == l) r = i; }
    }
    reverse(a + l, a + r + 1);
    for(int i = 1; i <= n; i++) cout << a[i] << ' ';
    cout << endl;
    
}

signed main(){
    int t = 0; cin >> t;
    while(t--) solve();
    return 0;
}

B.Odd Swap Sort

思路

相加为奇数才允许交换,那么我们分奇偶讨论,如果奇数序列和偶数序列中存在逆序对,那么必然不能成功排序(无法交换位置)。

Accepted Code

#include <bits/stdc++.h>
#define int long long
using namespace std;

#define yes puts("YES")
#define no puts("NO")

const int N = 100005;
int a[N];

inline void solve(){
    int n = 0; cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    int book1 = 0, book2 = 0;
    for(int i = 1; i <= n; i++){
        if(a[i] & 1){
            if(a[i] < book1){ no; return; }
            book1 = a[i];            
        }
        else{
            if(a[i] < book2){ no; return; }
            book2 = a[i];
        }
    }
    yes;
}

signed main(){
    int t = 0; cin >> t;
    while(t--) solve();
    return 0;
}

C.Inversion Graph

思路

逆序对之间连线,查连通块个数。

可以通过维护单调栈来做。但是还有更好写的做法:

对于两个连通块而言,其合并的条件是两个连通块里存在至少一个逆序对,也就是说靠前的大节点会包含后面的小节点。那么我们只需要对整个序列排序,然后寻找最大 i d id id归位的次数即可。

Accepted Code

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e5 + 10;

struct node{
    int id, val;
    const bool operator< (const node &aa){ return val < aa.val; }
}a[N];
//int a[N];

inline void solve(){
    int n = 0; cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i].val, a[i].id = i;
    sort(a + 1, a + 1 + n);
    int maxx = 0, cnt = 0;
    for(int i = 1; i <= n; i++){
        maxx = max(maxx, a[i].id);
        if(maxx == i) cnt++, maxx = a[i + 1].id;
    }
    cout << cnt << endl;
}

signed main(){
    int t = 0; cin >> t;
    while(t--) solve();
    return 0;
}

D.Big Brush

思路

题目要求还原染色步骤。。。一看就是个模拟。

首先遍历整张图,找到起始点,然后从起始点开始倒着删,得到操作序列后再倒过来输出,就是操作。

删除的过程可以BFS或者DFS(没写)。

Accepted Code

#include <bits/stdc++.h>
#define endl "\n"
const int dxy[] = {0, 1}, N = 1010;
int g[N][N];


inline void solve(){
    int n, m, cnt = 0; std::cin >> n >> m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) std::cin >> g[i][j];
    
    auto check = [&](int x, int y, int res = 0){
        if(x >=n || x < 1 || y >= m || y < 1) return 0;
        for(auto i : dxy) for(auto j : dxy){
            if(g[x + i][y + j]) res = g[x + i][y + j]; 
        }
        for(auto i : dxy) for(auto j : dxy){
            if(g[x + i][y + j] && g[x + i][y + j] != res) return 0; 
        }
        return res;
    };
    
    auto reset = [&](int x, int y){ 
        for(auto i : dxy) for(auto j : dxy) g[x + i][y + j] = 0;
    };

    struct node { int x, y, c; };
    std::stack<node> ans;
    std::queue<node> q;

    for(int i = 1; i < n; i++){
        for(int j = 1; j < m; j++){
            int res = check(i, j);
            if(res){ q.emplace(node{i, j, res}); break; }
        }
    }
    
    while(q.size()){
        node now = q.front(); q.pop();
        if(check(now.x, now.y) == now.c){
            ans.emplace(now);
            reset(now.x, now.y);
            for(int i = -1; i <= 1; i++){
                for(int j = -1; j <= 1; j++){
                    int nx = now.x + i, ny = now.y + j, res = check(nx, ny);
                    if(res) q.emplace(node{nx, ny, res});
                }
            }
        }
        
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(g[i][j]){ puts("-1"); return; }
        }
    }
    std::cout << ans.size() << endl;
    while(ans.size()){
        auto now = ans.top(); ans.pop();
        std::cout << now.x << ' ' << now.y << ' ' << now.c << endl;
    }
}

signed main(){
    std::ios_base::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    solve();
    return 0;
}

E.Colorful Operations

珂朵莉树+差分树状数组,具体见博客: CF1638E. Colorful Operations 珂朵莉树+差分树状数组_HeartFireY的博客-CSDN博客

举报

相关推荐

0 条评论