23.8.18 牛客暑期多校10部分题解

L - Grayscale Confusion

题目大意

n n n 个三元组 { r i ,   g i ,   b i } \{r_i,\space g_i,\space b_i\} {ri, gi, bi},需要构造一个数组 w i w_i wi 使得 w 1 = w 2 w_1=w_2 w1=w2 并且对于 ∀ i ,   j \forall i,\space j i, j 满足如果 r i < r j ,   g i < g j ,   b i < b j r_i<r_j,\space g_i<g_j,\space b_i<b_j ri<rj, gi<gj, bi<bj 那么 w i < w j w_i<w_j wi<wj,若不存在输出 − 1 -1 1

解题思路

根据数据范围可以想到满足条件的建有向边然后跑一遍宽度优先的拓扑

在搜索到 1 ,   2 1,\space 2 1, 2 两个点时暂停,记录,并作为第二遍拓扑的开始使得二者想等即可

听说题解还有更高级的做法,貌似可以用偏序的方法把时间复杂度优化到 O ( n ) O(n) O(n),可以自行了解

code

#include <bits/stdc++.h>
using namespace std;
const int N = 1009;
struct lol {int x, y;} e[N * N];
int n, ans, top[N], din[N], fl, r[N], g[N], b[N], w[N];
queue <int> q;
int bj(int x, int y) {return r[x] < r[y] && g[x] < g[y] && b[x] < b[y];}
void ein(int x, int y) {
    e[++ ans].x = top[x];
    e[ans].y = y;
    top[x] = ans;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i)
        scanf("%d%d%d", &r[i], &g[i], &b[i]);
    for (int i = 1; i <= n; ++ i)
        for (int j = i + 1; j <= n; ++ j) {
            if (bj(i, j)) ein(i, j), ++ din[j];
            if (bj(j, i)) ein(j, i), ++ din[i];
        }
    for (int i = 1; i <= n; ++ i) if (!din[i]) q.push(i);
    while (!q.empty()) {
        int x = q.front(); q.pop();
        if (x == 1 || x == 2) {fl += x; continue;}
        for (int i = top[x]; i; i = e[i].x) {
            int y = e[i].y;
            w[y] = max(w[y], w[x] + 1);
            -- din[y];
            if (!din[y]) q.push(y);
        }
    }
    if (fl != 3) {printf("-1"); return 0;}
    w[1] = w[2] = max(w[1], w[2]);
    q.push(1); q.push(2);
    while (!q.empty()) {
        int x = q.front(); q.pop();
        for (int i = top[x]; i; i = e[i].x) {
            int y = e[i].y;
            w[y] = max(w[y], w[x] + 1);
            -- din[y];
            if (!din[y]) q.push(y);
        }
    }
    for (int i = 1; i <= n; ++ i)
        printf("%d\n", w[i]);
    return 0;
}

D - Agnej

code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9;
int n, m, a[N], fl, ag;
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++ i) {
        for (int j = 1; j <= m; ++ j) scanf("%1d", &a[j]), a[j] += a[j - 1];
        if (m % 2 == 0) fl ^= (a[m] & 1);
        else if (a[m / 2 + 1] - a[m / 2] == 0) fl ^= (a[m] & 1);
        else if (a[m / 2] - a[0] == 0 || a[m] - a[m / 2 + 1] == 0) fl ^= ((a[m] & 1) ^ 1);
        else if (a[m / 2] - a[0] == 1 || a[m] - a[m / 2 + 1] == 1) fl ^= (a[m] & 1), ag ^= 1;
        else fl ^= (a[m] & 1);
    }
    printf(ag || fl ? "Alice" : "Bob");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值