Codeforces Round #648 (Div. 2)

今天推结论的题偏多

 

A

一个n*m的棋盘有初始状态,俩人下棋,每次选一个点,这一行跟这一列都没棋子,然后往这个点放入棋子

问对着下,谁能先下不动

找全0行数跟全0列数的最小值即可,根据奇偶判断

    #include<bits/stdc++.h>
    #define LL long long
    #define maxn 100010
    using namespace std;
     
    int mat[1010][1010];
     
    int main(){
        int T;
        cin >> T;
        while(T--){
            int n, m;
            cin >> n >> m;
            for(int i = 0; i < n; ++i){
                for(int j = 0; j < m; ++j){
                    cin >> mat[i][j];
                }
            }
            int cnt1 = 0, cnt2 = 0;
            for(int i = 0; i < n; ++i){
                bool is1 = true;
                for(int j = 0; j < m; ++j){
                    if(mat[i][j]){
                        is1 = false;
                    }
                }
                if(is1){
                    cnt1 = cnt1 + 1;
                }
            }
            for(int i = 0; i < m; ++i){
                bool is2 = true;
                for(int j = 0; j < n; ++j){
                    if(mat[j][i]){
                        is2 = false;
                    }
                }
                if(is2){
                    cnt2 = cnt2 + 1;
                }
            }
            if(min(cnt1, cnt2) % 2 == 0){
                cout << "Vivek" << endl;
            }
            else{
                cout << "Ashish" << endl;
            }
        } 
        return 0;
    } 

 

B

有n个元素,每个元素包含俩属性a跟b,当b不同时,俩元素可以交换位置,问能否让n个元素的a不递减排列

两个元素b相同时,也可以借助一个b不同的元素进行位置交换,所以只要有b不同的元素,就一定能转化为不递减排列

仅当所有元素b全部相同且排列不是非递减,才不能转化为不递减排列

#include<bits/stdc++.h>
#define LL long long
#define maxn 100010
using namespace std;
 
int a[maxn];
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while(T--){
        int n;
        cin >> n;
        bool add = true;
        for(int i = 0; i < n; ++i){
            cin >> a[i];
            if(i > 0 && a[i] < a[i - 1]){
                add = false;
            }
        }
        int t, sum = 0;
        for(int i = 0; i < n; ++i){
            cin >> t;
            sum = sum + t;
        }
        if((sum == 0 || sum == n) && !add){
            cout << "No" << endl;
        }
        else{
            cout << "Yes" << endl;
        }
    } 
    return 0;
} 

 

C

有两个排列a跟b,问能否让b排列左移或右移一定位置,让a跟b排列重合的尽可能多

我们用map记录a排列每个元素向左移多少个才能到b对应的那个元素,另一个map记录向右移多少个

然后求这两个map中,最大的second值即可

#include<bits/stdc++.h>
#define LL long long
#define maxn 200010
using namespace std;
 
int a[maxn], b[maxn], c[maxn], d[maxn];
 
map<int, int> mp1, mp2;
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int T;
    //cin >> T;
    T = 1;
    while(T--){
        int n;
        cin >> n;
        for(int i = 0; i < n; ++i){
            cin >> a[i];
            c[a[i]] = i;
        }
        int ans = 0;
        for(int i = 0; i < n; ++i){
            cin >> b[i];
            int diff = (i - c[b[i]] + n) % n;
            if(mp1.find(diff) == mp1.end()){
                mp1[diff] = 1;
            }
            else{
                mp1[diff] = mp1[diff] + 1;
            }
            ans = max(ans, mp1[diff]);
            if(mp2.find(n - diff) == mp2.end()){
                mp2[n - diff] = 1;
            }
            else{
                mp2[n - diff] = mp2[n - diff] + 1;
            }
            ans = max(ans, mp2[n - diff]);
        }
        cout << ans << endl;
    } 
    return 0;
} 

 

D

给一个n*m的地图,里面除了墙跟通路,还有B格(坏人)跟G格(好人),问你能否加一些墙,让所有坏人到不了出口((n,m)点),所有好人到的了出口

结论很简单,我们给坏人的上下左右,只要这一点不是坏人的位置都放上墙,然后判断出口能否dfs到所有好人

原因是如果每一个好人会被这样的墙堵上,说明坏人也可以从这条路走到终点,所以这样是正确的加墙方式

#include<bits/stdc++.h>
#define LL long long
#define maxn 55
using namespace std;
 
char a[maxn][maxn];
 
bool vis[maxn][maxn];
 
int n, m;
 
int _dfs(int x, int y){
    if(x < 0 || x >= n || y < 0 || y >= m){
        return 0;
    }
    if(vis[x][y] || a[x][y] == '#'){
        return 0;
    }
    vis[x][y] = 1;
    int ret = 0;
    if(a[x][y] == 'G'){
        ret = ret + 1;
    }
    ret = ret + _dfs(x + 1, y);
    ret = ret + _dfs(x - 1, y);
    ret = ret + _dfs(x, y + 1);
    ret = ret + _dfs(x, y - 1);
    return ret;
}
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while(T--){
        cin >> n >> m;
        int sum = 0;
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < m; ++j){
                cin >> a[i][j];
                if(a[i][j] == 'G'){
                    sum = sum + 1;
                }
            }
        } 
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < m; ++j){
                if(a[i][j] == 'B'){
                    if(i != 0){
                        if(a[i - 1][j] != 'B'){
                            a[i - 1][j] = '#';
                        }
                    }
                    if(i != n - 1){
                        if(a[i + 1][j] != 'B'){
                            a[i + 1][j] = '#';    
                        }
                    }
                    if(j != 0){
                        if(a[i][j - 1] != 'B'){
                            a[i][j - 1] = '#';
                        }
                    }
                    if(j != m - 1){
                        if(a[i][j + 1] != 'B'){
                            a[i][j + 1] = '#';    
                        }
                    }
                }
            }
        }
        memset(vis, 0, sizeof vis);
        if(sum == _dfs(n - 1, m - 1)){
            cout << "Yes" << endl;
        }
        else{
            cout << "No" << endl;
        }
    } 
    return 0;
} 

 

E

有n个元素,让你从其中选出k个,对于每一个二进制位,如果这一位有max(k-2,1)个元素这一位是1,那么答案这一位是1,让你确定k跟这k个元素,输出最大值

结论是选3个元素最优,如果选2个元素,那么选第三个元素的答案一定大于等于选两个元素的答案,因为max(k-2,1)都是1,如果选4个元素,那么只有在选3个元素答案等于选的第4个元素时,才能让答案不减少,不然答案一定会减少(在之前选的3个元素是最优的情况下)

所以我们选最多3个元素,找他们并的最大值即可

#include<bits/stdc++.h>
#define LL long long
#define maxn 505
using namespace std;
 
LL a[maxn];
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i){
        cin >> a[i];
    }
    LL ans = 0;
    if(n <= 3){
        for(int i = 0; i < n; ++i){
            ans = ans | a[i];
        }
        cout << ans << endl;
        return 0; 
    }
    for(int i = 0; i < n; ++i){
        for(int j = i + 1; j < n; ++j){
            for(int k = j + 1; k < n; ++k){
                ans = max(ans, a[i] | a[j] | a[k]);
            }
        }
    }
    cout << ans << endl;
    return 0;
} 

 

F题看起来也是能做的题,但是我昨天晚上做完E就去睡了

经典结论场,全是考验思维的题

posted @ 2020-06-08 09:07  Stein_Gate_Amadeus  阅读(236)  评论(0)    收藏  举报