codeforces round 956 div2

A Array Divisibility

问题:

思路:注意到1.2.3.4.5.6....就是一组合法解

代码:

#include <bits/stdc++.h>

using namespace std;

void solve() {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++ ) cout << i << " ";
    cout << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while(t -- ) {
        solve();
    }
    return 0;
}

B cornor twist

问题:

思路:贪心的从第一行第一列开始构造出和b一样的数组,如果构造完后a != b则没有合法解

代码:
 

#include <bits/stdc++.h>

using namespace std;

const int N = 510;

int n, m;
char a[N][N];
char b[N][N];

void solve() {
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ ) {
        for(int j = 1; j <= m; j ++ ) {
            cin >> a[i][j];                    
        }
    }
    
    for(int i = 1; i <= n; i ++ ) {
        for(int j = 1; j <= m; j ++ ) {
            cin >> b[i][j];
        }
    }
    
    for(int i = 1; i <= n - 1; i ++ ) {
        for(int j = 1; j <= m - 1; j ++ ) {
            if(a[i][j] != b[i][j]) {
                if(((a[i][j] + 1) % 3) == b[i][j]) {
                    (a[i][j] += 1) %= 3;
                    (a[i + 1][j + 1] += 1) %= 3;
                    (a[i][j + 1] += 2) %= 3;
                    (a[i + 1][j] += 2) %= 3;
                } else {
                    (a[i][j] += 2) %= 3;
                    (a[i + 1][j + 1] += 2) %= 3;
                    (a[i][j + 1] += 1) %= 3;
                    (a[i + 1][j] += 1) %= 3;
                }
            }
        }
    }
    
    bool flag = true;
    for(int i = 1; i <= n; i ++ ) {
        for(int j = 1; j <= m; j ++ ) {
            if(a[i][j] != b[i][j]) flag = false;
        }
    }
    
    if(flag) cout << "YES" << endl;
    else cout << "NO" << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while(t -- ) {
        solve();
    }
    return 0;
}

C have your cake eat it too

问题:

思路:就是对abc的一个排列组合,每组排列中做一下前缀和,嵌套个二分(不用二分直接暴力也行)

代码:

#include <bits/stdc++.h>

using namespace std;

void solve() {
    int n;
    cin >> n;
    vector<long long> a(n + 1), b(n + 1), c(n + 1);
    for(int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        a[i] += a[i - 1];
    }

    for(int j = 1; j <= n; j ++ ) {
        cin >> b[j];
        b[j] += b[j - 1];
    }

    long long tot = 0;
    for(int k = 1; k <= n; k ++ ) {
        cin >> c[k];
        tot += c[k];
        c[k] +=  c[k - 1];
    }

    vector<int> ans(6);
    auto check = [&](vector<long long> &a, vector<long long> &b, vector<long long> &c) {
        int l = 1, r = n;
        while(l < r) {
            int mid = l + r >> 1;
            if(a[mid] >= (tot + 2) / 3) r = mid;
            else l = mid + 1; 
        }
        if(a[l] >= (tot + 2) / 3 && l <= n - 2) {
            ans[0] = 1;
            ans[1] = l;
        } else return false;

        int tmp = l;
        l ++, r = n;
        while(l < r) {
            int mid = l + r >> 1;
            if(b[mid] - b[tmp] >= (tot + 2) / 3) r = mid;
            else l = mid + 1;
        }
        if(b[l] - b[tmp] >= (tot + 2) / 3 && l <= n - 1) {
            ans[2] = tmp + 1;
            ans[3] = l;
        } else return false;

        tmp = l;
        l ++, r = n;
        while(l < r) {
            int mid = l + r >> 1;
            if(c[mid] - c[tmp] >= (tot + 2) / 3) r = mid;
            else l = mid + 1;
        }
        if(c[l] - c[tmp] >= (tot + 2) / 3) {
            ans[4] = tmp + 1;
            ans[5] = l;
        } else return false;
        return true;
    };

    if(check(a, b, c)) {
        for(auto t: ans) cout << t << " ";
        cout << endl;
        return;
    } else if(check(a, c, b)) {
        cout << ans[0] << " " << ans[1] << " " << ans[4] << " " << ans[5] << " " << ans[2] << " " << ans[3] << endl;
        return;
    } else if(check(b, a, c)) {
         cout << ans[2] << " " << ans[3] << " " << ans[0] << " " << ans[1] << " " << ans[4] << " " << ans[5] << endl;
        return;
    } else if(check(b, c, a)) {
         cout << ans[2] << " " << ans[3] << " " << ans[4] << " " << ans[5] << " " << ans[0] << " " << ans[1] << endl;
        return;
    } else if(check(c, a, b)) {
         cout << ans[4] << " " << ans[5] << " " << ans[0] << " " << ans[1] << " " << ans[2] << " " << ans[3] << endl;
        return;
    } else if(check(c, b, a)) {
         cout << ans[4] << " " << ans[5] << " " << ans[2] << " " << ans[3] << " " << ans[0] << " " << ans[1] << endl;
        return;
    } else cout << "-1" << endl;
}

int main() {
    int t;
    cin >> t;
    while(t -- ) {
        solve();
    }
    return 0;
}

D swap dilemma

问题:

思路:我们现在思考一个这样的问题:交换相距任意长度的元素是否都可以通过交换相邻元素实现,答案是一定的,自己模拟一下很容易就可以证明。那么现在交换相距任意距离的元素这个条件可以被我们替换成交换任意相邻元素。对于一组没有重复元素的序列,我们每一次交换相邻元素都会让该数组的逆序对数量 + 1或者 - 1也就是说,我们每一次操作都会使得ab两个数组逆序对数量的差值不变,或者减2,或者加2,如果我们可以让ab两个数组的逆序对数量相同,那么ab数组就可以相互转换,也就是如果ab逆序对数量和为偶数,数据就是合法的

这里逆序对可以用归并排序,也可以用树状数组

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 410;
const int M = 2e5 + 10;

long long g[N][N];
pair<int, int> b[M];
long long len[M];

int main() {
    int n, m;
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    for(int i = 1; i <= m; i ++ ) {
        long long v, u, t;
        cin >> v >> u >> t;
        b[i] = {v, u};
        g[v][u] = min(g[v][u], t);
        g[u][v] = min(g[u][v], t);
        len[i] = t;
    }    

    for(int i = 1; i <= n; i ++ ) g[i][i] = 0;
    for(int k = 1; k <= n; k ++ ) {
        for(int i = 1; i <= n; i ++ ) {
            for(int j = 1; j <= n; j ++ ) {
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
            }
        }
    }
    //cout << g[1][2] << endl;
    int q;
    cin >> q;
    for(int o = 1; o <= q; o ++ ) {
        int k;
        cin >> k;
        vector<int> c(k + 1);
        long long tmp = 0;
        for(int i = 1; i <= k; i ++ ) {
            cin >> c[i];
            tmp += len[c[i]];
        }
        long long ans = 1e18;
        vector<pair<int, int>> a(k + 1);
        function<void(int)> dfs = [&](int u) {
            if(u == k + 1) {
                //cout << "YES" << endl;
                //for(auto t: a) cout << t.first << " " << t.second << endl;
                long long res = 0;
                res += g[1][a[1].first];
                //cout << g[1][a[1].first] << endl;
                res += g[a[k].second][n];
                for(int i = 2; i <= k; i ++ ) {
                    res += g[a[i - 1].second][a[i].first];
                }
                ans = min(ans, res);
                return;
            }

            for(int i = 1; i <= 2; i ++ ) {
                if(i == 1) {
                    a[u].first = b[c[u]].first;
                    a[u].second = b[c[u]].second;
                } else {
                    a[u].first = b[c[u]].second;
                    a[u].second = b[c[u]].first;
                }
                dfs(u + 1);
            }
        };

        do {
            dfs(1);
        } while(next_permutation(c.begin() + 1, c.end()));
        //for(int i = 1; i <= k; i ++ ) cout << c[i] << " ";
        //cout << tmp <<endl;
        cout << ans + tmp << endl;
    }
    return 0;
}

E

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值