Codeforces Round #417 (Div. 2) 题解

题解

A. Sagheer and Crossroads

额。题意杀。

半天没搞懂这题要干啥!代码好丑。

#include <iostream>
#include <cstdio>
using namespace std;
int m[5][5];
int main()
{
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
            cin >> m[i][j];

    int ok = 1;
    if(m[1][4]) {
        if(m[1][1]||m[1][2]||m[1][3]||m[2][1]||m[4][3]||m[3][2]) ok = 0;
    }
    if(m[2][4]) {
        if(m[2][1]||m[2][2]||m[2][3]||m[3][1]||m[4][2]||m[1][3]) ok = 0;
    }
    if(m[3][4]) {
        if(m[3][1]||m[3][2]||m[3][3]||m[4][1]||m[1][2]||m[2][3]) ok = 0;
    }
    if(m[4][4]) {
        if(m[4][1]||m[4][2]||m[4][3]||m[1][1]||m[2][2]||m[3][3]) ok = 0;
    }
    printf("%s\n", (ok==0)?"YES":"NO");
}

B. Sagheer, the Hausmeister

又是题意杀。英语真是辣鸡。【不过比一个叫做“黄焖蓉”的队友还是好那么一点】

施展一下DP这题还是不太难的。

dp[i][0]: 把前i楼全部搞定,且位于第i楼左端 の 最小耗费

dp[i][1]: 把前i楼全部搞定,且位于第i楼右端 の 最小耗费

转移方式有四种:

左左,右右,左右,右左。

然后是一堆特判:

  1. 比较高的楼层一片黑暗,所以无需“独上危楼听风雨,举杯邀影念旧情”啦!
  2. 某一个楼层灯全是灭的,这种楼层吓死人了。所以状态转移时姿势要变一下。

代码还是写得这么辣鸡。我也很绝望

#include <iostream>
#include <cstring>
using namespace std;
int n, m, dp[102][2];
char s[102][102];
int main()
{
    cin >> n >> m;
    for(int i=n;i>=1;i--) {
        scanf("%s", s[i]+1);
    }
    dp[0][0] = -1, dp[0][1] = 100000000;
    while(1) {
        int ac = 0;
        for(int i=2;i<=m+1;i++) {
            if(s[n][i] == '1') {
                ac = 1;
            }
        }
        if(ac == 0) n--;
        if(ac) break;
        if(n==0) break;
    }

    if(n == 0) {
        cout << 0 << endl;
        return 0;
    } 

    for(int i=1;i<n;i++) {
        
        int p1 = -1, p2 = -1;
        for(int j=2;j<=m+1;j++) {
            if(s[i][j] == '1') {
                p1 = j; break;
            }
        }
        for(int j=m+1;j>=2;j--) {
            if(s[i][j] == '1') {
                p2 = j; break;
            }
        }

        if(p1 == -1) {
            dp[i][0] = min(dp[i-1][0]+1, dp[i-1][1]+m+2);
            dp[i][1] = min(dp[i-1][1]+1, dp[i-1][0]+m+2);
            continue;
        }

        dp[i][0] = min(dp[i-1][1] + m+2, dp[i-1][0] + 1 + 2*(p2-1));
        dp[i][1] = min(dp[i-1][0] + m+2, dp[i-1][1] + 1 + 2*(m+2-p1));

    }
    int ans = 1000000000;

    for(int i=2;i<=m+1;i++) {
        if(s[n][i] == '1') {
            ans = min(ans, dp[n-1][1]+m+3-i);
            break;
        }
    }

    for(int i=m+1;i>=2;i--) {
        if(s[n][i] == '1') {
            ans = min(ans, dp[n-1][0]+i);
            break;
        }
    }

    printf("%d\n", ans);
}

C. Sagheer and Nubian Market

C比B还是简单那么一点点。

二分要拿多少个物品。每一次check都捡最便宜的物品。就行了。

code:

我觉得自己还是别写代码了比较好。:(´°ω°`」 ∠):

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;

LL it[100000+10], a[100000+10];

LL n, S, T;

bool chk(int mid) {
    for(int i=1;i<=n;i++) {
        a[i] = it[i] + (LL)mid * i;
    }
    sort(a+1, a+1+n);
    LL sum = 0;
    for(int i=1;i<=mid;i++) {
        sum += a[i];
    }
    bool ok_ = (sum <= S);
    if(ok_) T = sum;
    return ok_;
}

int main()
{
    cin >> n >> S;
    for(int i=1;i<=n;i++) {
        scanf("%lld", &it[i]);
    }
    int L = 0, R = n;
    while(R - L > 1) {
        int mid = (L+R)/2;
        if(chk(mid)) {
            L = mid;
        } else {
            R = mid;
        }
    }
    if(chk(R)) L = R;
    
    chk(L);
    cout << L << " " << T << endl;

}

E. Sagheer and Apple Tree

我们先将这棵树各节点红蓝交替染色。如果叶子节点为红色的。那么蓝色节点上的苹果对最终胜负就没有影响了。(因为蓝色节点上的苹果只能移动到红色节点,然后下一个人可以把这些苹果又移到蓝色节点上)【这玩意就是传说中的阶梯博弈模型

1)若红色节点上的nim和为0.

那么执行完交换操作后,仍要保持住红色节点nim和为0的状态所以可以

  1. 交换两个蓝色节点
  2. 交换两个红色节点
  3. 将两个数目相等是红蓝节点交换

2)若红色节点上的nim和不为0.

那我们得抢救一番,使得红色节点nim和为0.拿map施展一下即可。

#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef long long LL;
const int NICO = 100000+10;
int n, dep[NICO], a[NICO], p[NICO];
vector<int> v[NICO], v1, v2; 
map<int, int> mp;
void dfs(int x) {
    for(int i=0;i<v[x].size();i++) {
        dep[v[x][i]] = dep[x] + 1;
        dfs(v[x][i]);
    }
}
int main() {
    scanf("%d", &n);
    for(int i=1;i<=n;i++) scanf("%d", &a[i]);
    for(int i=2;i<=n;i++) {
        scanf("%d", &p[i]);
        v[p[i]].push_back(i);
    } 
    dep[1]=1; dfs(1);
    int mx = -1; 
    for(int i=1;i<=n;i++) {
        mx = max(mx, dep[i]);
    }

    int nim = 0;
    for(int i=1;i<=n;i++) {
        if(dep[i]%2 == mx%2) {
            v1.push_back(a[i]); 
            nim ^= a[i];
        } else {
            v2.push_back(a[i]);
            mp[a[i]] ++;
        }   
    } 

    LL ans = 0;
    if(nim == 0) {  
        ans += (LL)v1.size()*((LL)v1.size() - 1)/2;
        ans += (LL)v2.size()*((LL)v2.size() - 1)/2;
    }

    for(int i=0;i<v1.size();i++) {
        ans += mp[nim^v1[i]];
    }
    cout << ans << endl;

}

比赛过程

11 min A题 1Y 被自己惊人英语水平震撼。完全靠看样例解释和瞎猜过日子。

30 min C题 1Y 二分一直死循环。边界杀。

65 min B题 1Y 被自己惊人的码力震撼。dp写得太迷了。

然后在flash造反,网速爆炸的环境下hack了几发A.

然后是E题。排骨龙选手,比赛后半段一直处于啥都不想干的咸鱼模式。到了105分钟的时候终于终于终于开始读E题了,先是读错题,读对后,啥也没想出。其实E很水的呀!(° ꈊ °)✧˖°オホッ! 比赛排骨龙一直处于脑子生锈状态。哦,不对,是没脑子状态(бвб)。。最近排骨龙选手,经历了鼠粮不见了+饮水机不见了+快递半天不到这一系列大快人心的事情。所以比较躁动。(( ≧ꀦ≦))

1.%qls E题的全场FB。

2.%宇宙智障 E题居然得到施展了+代码全场最短。【宇宙智障都能A的题,一定是水题吧!
(◍ ૢ´꒳`◍ ૢ)】

posted @ 2017-06-02 11:06  RUSH_D_CAT  阅读(358)  评论(0编辑  收藏  举报