Codeforces Round #557 (Div. 2)简要题解

A. Zoning Restrictions Again

分析:根据题意简单模拟一下就可以了。

#include "bits/stdc++.h"

using namespace std;
int a[54];

int main() {
    int n, m, h;
    cin >> n >> h >> m;
    int l, r, x;
    for (int i = 0; i <= n; ++i) {
        a[i] = h;
    }
    while (m--) {
        cin >> l >> r >> x;
        for (int i = l; i <= r; ++i) {
            a[i] = min(x, a[i]);
        }
    }
    long long ans = 0;
    for (int i = 1; i <= n; ++i) {
        ans += a[i] * a[i];
    }
    cout << ans << endl;
}

B. Double Matrix

分析:显而易见的,把每个位置较小的数放在第一个mat里面,较大的放在第二个mat里面,这样是最优的,然后再判断一下就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[54][54], b[54][54];
 
int main() {
    int n,m;
    cin >> n>>m;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            scanf("%d", &a[i][j]);
        }
    }
 
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            scanf("%d", &b[i][j]);
            if (a[i][j] > b[i][j])swap(a[i][j], b[i][j]);
        }
    }
    /*for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            printf("%d ",a[i][j]);
        }
        puts("");
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            printf("%d ",b[i][j]);
        }
        puts("");
    }*/
    bool ok = 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = 2; j <= m; ++j) {
            if (a[i][j] <= a[i][j - 1])ok = 0;
            if (b[i][j] <= b[i][j - 1])ok = 0;
        }
    }
    for (int j = 1; j <= m; ++j) {
        for (int i = 2; i <= n; ++i) {
            if (a[i][j] <= a[i-1][j])ok = 0;
            if (b[i][j] <= b[i-1][j])ok = 0;
        }
    }
    if(ok)puts("Possible");
    else puts("Impossible");
}
 

C. Hide and Seek

分析:如果k=0,那么ans  = 3*n-2。当k!=0时,减掉数组的长度位2的子序列出现过的情况就可以了。

#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9+7;
struct node
{
    int x,y;
    bool friend operator < (node a,node b){
        return a.x==b.x?a.y<b.y:a.x<b.x;
    }
    bool friend operator == (node a,node b){
        return a.x==b.x&&a.y==b.y;
    }
};
int main(){
    int n,k;
    cin>>n>>k;
    int ans = 3*n - 2;
    int x;
    unordered_map<int,int>mp;
    map<node,bool>mp2;
    for (int i = 0; i < k; ++i) {
        cin>> x;
        if(mp2.count({x+1,x})== 0&& mp.count(x+1)){
            mp2[{x+1,x}]=1;
            ans--;
        }
        if(!mp2.count({x-1,x}) && mp.count(x-1)){
            mp2[{x-1,x}]=1;
            ans--;
        }
        mp[x]++;
    }
    cout<<ans - mp.size()<<endl;
}

D. Chladni Figure

分析:首先,转动n个点必然重合,若存在小于n的答案,那么一定是n的因子,且小于等于n/2。

那么直接枚举n的因子,然后暴力判断是否重合就可以了。

#include "bits/stdc++.h"
 
using namespace std;
const int mod = 1e9 + 7;
vector<pair<int, int>> v;
map<pair<int,int>,bool>mp;
int main() {
    int n, m;
    cin >> n >> m;
    int A, B;
    for (int i = 0; i < m; ++i) {
        scanf("%d%d", &A, &B);
        if (A > B)swap(A, B);
        v.push_back(make_pair(A, B));
        mp[make_pair(A,B)]=1;
        /*if (B - A <= n / 2) {
            v.push_back(make_pair(A, B));
            mp[make_pair(A,B)]=1;
        }
        else{
            v.push_back(make_pair(B, A));
            mp[make_pair(B,A)]=1;
        }*/
 
    }
    sort(v.begin(),v.end());
    bool ok = 0;
    bool yes = 0;
    pair<int,int>t;
    for (int i = 1; i <= n/2 && !yes; ++i) {
        if(n%i)continue;
        ok=1;
        for (int j = 0; j < v.size() && ok; ++j) {
            t = v[j];
            t.first+=i;
            t.second+=i;
            t.first%=n;
            t.second%=n;
            if(t.first==0)t.first=n;
            if(t.second==0)t.second=n;
            if(t.first>t.second)swap(t.first,t.second);
            if(mp.count(t))continue;
            else ok = 0;
        }
        if(ok)yes = 1;
    }
    if(yes)puts("Yes");
    else puts("No");
}

E. Thanos Nim

分析:首先朴素的想,当轮到某个人的时候,这个人一定不能率先把某一对拿到0,因为下轮的人只需要拿n/2个0就赢了。

那么也不能率先拿到1(意思是拿完之后不能有<=n/2个1,大于是可以的),因为这样下轮的人只需要拿n/2个1,那么在下轮必定会拿出一个以上的0(因为此时1的个数>n/2)。

那么策略就出来了,如果此时有大于等于n/2个数严格大于最小值,那么我就将这n/2个数拿到当前的最小值。那么下轮的人必定会减少这个最小值,只需要重复操作就可以了,最后必定是后手的人先把某堆拿到0,这样就赢了。

所以简单判断一下是否存在大于等于n/2个数严格大于最小值就可以了。

#include "bits/stdc++.h"
 
using namespace std;
const int mod = 1e9 + 7;
int a[54];
int main() {
    int n;
    cin>>n;
    int mini = 100;
    for (int i = 0; i < n; ++i) {
        scanf("%d",&a[i]);
        mini = min(mini,a[i]);
    }
    int cnt = 0;
    for (int i = 0; i < n; ++i) {
        if(a[i]>mini)cnt++;
    }
    if(cnt>=n/2)puts("Alice");
    else 
    puts("Bob");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值