Codeforces Round #648 (Div. 2) 1365 ABCDEF題解

首先

Cue一下隊友鏈接:

核心選手:https://me.csdn.net/qq_43559193

核心選手:https://me.csdn.net/weixin_43916298

比賽鏈接:https://codeforces.ml/contest/1362

目錄

A. Matrix Game

題目大意:

題目思路:

Code:

B. Trouble Sort

題目大意:

題目思路:

Code:

C. Rotation Matching

題目大意:

題目思路:

D. Solve The Maze

題目大意:

題目思路:

Code:

E. Maximum Subsequence Value

題目大意:

題目思路:

Code:

F. Swaps Again

題目大意:

題目思路:

Code:


 

 

A. Matrix Game

題目大意:

兩個人玩遊戲,每個人可以放石子,放石子的要求是當且僅當 該行或者該列沒有石子,不能放石子的人失敗。

給出初始棋盤佈局

雙方都採取最優策略,問誰會贏?

題目思路:

博弈論嘛。

再結合這個題是A題,肯定不是太難的博弈。

必輸態很容易,就是沒有行與列可以,所以看一下行與列的最小值

判斷一下奇偶性就可以了

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll mp[105][105];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);read(m);
        for(int i=1;i<=n;i++){
            for(int k=1;k<=m;k++)
                read(mp[i][k]);
        }
        ll ans = 0,ans1 = 0;
        for(int i=1;i<=n;i++){
            ll p = 0;
            for(int k=1;k<=m;k++){
                if(mp[i][k]) break;
                if(k == m) ans++;
            }
        }
        for(int k=1;k<=m;k++){
            for(int i=1;i<=n;i++){
                if(mp[i][k]) break;
                if(i == n) ans1++;
            }
        }
        ll temp = min(ans,ans1);
        if(temp&1) printf("Ashish\n");
        else printf("Vivek\n");
    }
    return 0;
}
/**
1[2[a]3[b]4[1[b]2[c]]]
aabbb[bccb
**/

B. Trouble Sort

題目大意:

給出一個a數組與b數組,ai與aj可以交換當且僅當bi!=bj 

b數組只包含0、1

問能否通過若干次交換後使得a數組單調不下降

題目思路:

首先明白一個結論:01同時存在一定可以(老結論了,不信可以證明一下:所有交換的元素都可以通過一個元素進行交換,實現兩者的交換)

沒有01同時存在的話,只能看原數組是否有序了

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll a[maxn],b[maxn];
struct node{
    ll w;
    int id;
}save[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        int f = 0;
        a[0] = -1;
        for(int i=1;i<=n;i++){
            read(a[i]);
            if(a[i]<a[i-1]) f = 1;
        }
        ll f1 = 0,f2 = 0;
        for(int i=1;i<=n;i++){
            read(b[i]);
            if(b[i]) f1++;
            else f2++;
        }
       // debug(f1);
       // debug(f2);
        if(!f1||!f2){
            if(f) printf("No\n");
            else printf("Yes\n");
        }
        else printf("Yes\n");
    }
    return 0;
}
/**
1[2[a]3[b]4[1[b]2[c]]]
aabbb[bccb
**/

C. Rotation Matching

題目大意:

給出a,b兩個數組,每次使得a向左或者向右移動k位(k取任意值),問最大能有多少個ai = bi

題目思路:

首先,由於沒有規定移動位數的限制,所以向右移動可以代替向左移動

所以控制b不變,使得a向右移動,此時最多移動n-1位,超過n-1位就爲一個循環節了

所以看一下每個數字可以移動多少位才能與b中的數字對應

最後求移動位數貢獻的最大值,就是數字個數了

一個經驗:做過很多全排列的題、基本都跟位置有關係,因爲全排列 位置 -> 值 是一個一一映射

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll a[maxn],b[maxn];
int pos[maxn];
int val[maxn];
int main(){
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<=n;i++){
        read(b[i]);
        pos[b[i]] = i;
    }
    for(int i=1;i<=n;i++){
        int temp = pos[a[i]];
        if(temp>=i) val[temp-i]++;
        else val[n-i+temp]++;
    }
    int maxl = 0;
    for(int i=0;i<=n-1;i++){
        maxl = max(maxl,val[i]);
    }
    printf("%d\n",maxl);
    return 0;
}
/**
1[2[a]3[b]4[1[b]2[c]]]
aabbb[bccb
**/

D. Solve The Maze

題目大意:

給出一張地圖,G是好人,B是壞人,.是空地,#是牆,終點是n,m

問能否讓一些點變爲牆,從而使得所有的好人都能到達終點,而所有的壞人都到達不了終點。

題目思路:

考慮把壞人封鎖起來,然後看所有好人能否到達終點即可

如何封鎖是個問題、這裏也是莽了一下,首先貪心的去想,如果要對好人的影響最小,那麼封鎖的範圍應該最小。

所以首先考慮 B 能否到達終點,如若不到達終點不需要封鎖

到達終點的話,莽了一下,封鎖相鄰的四個點。

然而過了,有沒有大佬可以證明一下這是正確的,評論區可以討論(我感覺有一種方案,封鎖下出口,而不封鎖上出口,因爲上出口到達不了,然而此時封鎖上出口會使得有一個好人不過,就這種情況,不知道我想複雜了還是怎麼)

封鎖之後,再看一下所有好人是否都可以到就可以了

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
char mp[105][105];
int visp[55][55];
int vis[55][55];
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};
int judge(int x,int y){
    if(x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]!='#') return 1;
    return 0;
}
int bfs(int sx,int sy){
    queue<pair<int,int>>q;
    for(int i=1;i<=n;i++){
        for(int k=1;k<=m;k++){
            vis[i][k] = 0;
        }
    }
    if(mp[sx][sy] == '#') return 0;
    q.push({sx,sy});
    vis[sx][sy] = 1;
    while(!q.empty()){
        auto u = q.front();q.pop();
        int x = u.first,y = u.second;
        for(int i=0;i<4;i++){
            int mx = x+dx[i],my = y+dy[i];
            if(judge(mx,my)&&!vis[mx][my]){
                q.push({mx,my});
                vis[mx][my] = 1;
            }
        }
    }
    return vis[n][m];
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);read(m);
        memset(visp,0,sizeof(visp));
        for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
        bfs(n,m);
        for(int i=1;i<=n;i++){
            for(int k=1;k<=m;k++){
                if(mp[i][k] == 'B'&&vis[i][k]) visp[i][k] = 1;
            }
        }
        int f = 0;
        for(int i=1;i<=n;i++){
            for(int k=1;k<=m;k++){
                if(visp[i][k]){
                    for(int j=0;j<4;j++){
                        int mx = i +dx[j],my = k+dy[j];
                        if(judge(mx,my)){
                            if(mp[mx][my] == 'G') f = 1;
                            mp[mx][my] = '#';
                        }
                    }
                }
            }
        }
        bfs(n,m);
        for(int i=1;i<=n;i++){
            for(int k=1;k<=m;k++){
                if(mp[i][k]=='G'&&!vis[i][k]) f = 1;
            }
        }
        if(f) printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}
/**
3
011
100
111
**/

E. Maximum Subsequence Value

題目大意:

要求你選出一段子序列,假設長度爲k,將這個子序列的個元素二進制拆分。

如果第i位上的1的個數 >= max(k-2,1) 那麼該位就會貢獻 2^i

問子序列的最大貢獻是多少?

題目思路:

k只可以取1、2、3

這裏證明一下:

其實1 2 3顯然成立,所以只需要證明大於3的不會產生比1 2 3大的貢獻即可

如果一段序列 在第i位上不滿足,那麼如果擴充元素的個數,新增元素在該位只能是0或者1

如果是0,序列長度增加1,限制條件max(k-2,1)也增加1,但是該位沒有增加,所以不會產生貢獻

如果是1,序列長度增加1,限制條件max(k-2,1)也增加1,該位增加+1,因爲之前不滿足,所以現在也不滿足

所以,對於長度爲3的子序列來說,如果想要在其上面擴充元素,滿足的一定還滿足,不滿足的一定還是不滿足,所以擴充是沒有用的。

所以只需要考慮1、2、3的情況

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll num[maxn];
ll c[65];
vector<int>v;
int main(){
    read(n);

    ll maxl = 0;
    for(int i=1;i<=n;i++){
        read(num[i]);
        maxl = max(maxl,num[i]);
        for(int k=0;k<=62;k++) c[k] += ((num[i]>>k&1)?1:0);
    }
    for(int i=1;i<=n;i++){
        for(int k=i+1;k<=n;k++){
            maxl = max(maxl,num[i]|num[k]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int k=i+1;k<=n;k++){
            for(int j=k+1;j<=n;j++){
                maxl =max(maxl,((num[i]|num[k])|num[j]));
            }
        }
    }
    printf("%lld\n",maxl);
    return 0;
}
/**
3
011
100
111
**/

F. Swaps Again

題目大意:

給出a數組和b數組,每次可以對a數組進行操作,將前k個與後k個交換(k<n/2)。

問若干次交換後能否得到數組b

題目思路:

這個應該是規律或者結論題?

首先要發現一個性質:如果x和y對稱,那麼無論怎麼交換依然對稱。

1 2 5 6 :1對應6 ,2對應5

交換後:

5 6 1 2:1依然對應6,2依然對應5

所以我們就只需要看一下b數組的對應關係,如果a數組可以滿足這所有的對應關係,那麼每組對應關係無論怎麼交換都是可以得到的

所以只需要考慮一下對稱性判斷就好了,怎麼判斷對稱性呢?

a_i太大了,但是n確很小,所以考慮把a_i離散化,用一個二維數組來標記一下

a[x][y]標記一下x對應y的關係有多少個

看a中的關係能否全部滿足即可:此時注意關係是雙向的,需要雙向判斷

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll num[maxn];
ll judge[505][505];
vector<int>v;
int getid(ll x){
    return lower_bound(v.begin(),v.end(),x)-v.begin() +1;
}
ll a[maxn],b[maxn],c[maxn],d[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        for(int i=0;i<=n;i++){
            for(int k=0;k<=n;k++){
                judge[i][k] = 0;
            }
        }
        v.clear();
        for(int i=1;i<=n;i++){
            read(a[i]);
            c[i] = a[i];
            v.push_back(a[i]);
        }
        for(int i=1;i<=n;i++){
            read(b[i]);
            d[i] = b[i];
        }
        sort(a+1,a+1+n);
        sort(b+1,b+1+n);
        int f = 0;
        for(int i=1;i<=n;i++){
            if(a[i] != b[i]) f = 1;
        }
        if(f){
            printf("No\n");
            continue;
        }
        sort(v.begin(),v.end());//排序
        v.erase(unique(v.begin(),v.end()),v.end());
        for(int i=1;i<=n;i++){
            int id1 = getid(c[i]);
            int id2 = getid(c[n-i+1]);
            judge[id1][id2]++;
            judge[id2][id1]++;
        }
        for(int i=1;i<=n;i++){
            int id1 = getid(d[i]);
            int id2 = getid(d[n-i+1]);
            if(judge[id1][id2]>0&&judge[id2][id1]>0){
                judge[id1][id2] --;
                judge[id2][id1] --;
            }
            else{
                f = 1;
                break;
            }
        }
        if(f) printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}
/**
3
011
100
111
**/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章