Codeforces Round 895 (Div. 3)

A. Two Vessels

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int mod = 1e9 + 7;
using i64 = long long;


void solve() {
    int a, b, c;
    cin >> a >> b >> c;
    a = abs( a - b ) , c = c * 2 ;
    cout << ( a + c - 1 ) / c << "\n";
}

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

B. The Corridor or There and Back Again

二分答案,暴力判断

#include <bits/stdc++.h>

using namespace std;

#define int long long

constexpr int mod = 1e9 + 7, inf = 1e18;
using i64 = long long;
using pii = pair<int, int>;

void solve() {
    int n;
    cin >> n;
    vector<pii> a(n);
    for (auto &[d, s]: a) cin >> d >> s;
    sort(a.begin(), a.end());
    int l = 0, r = inf, res = -1;
    for (int mid, flag; l <= r;) {
        mid = (l + r) >> 1, flag = 1;
        for (auto [d, s]: a) {
            if (d > mid) break;
            if ((mid - d) * 2 < s) continue;
            flag = 0;
            break;
        }
        if( flag ) res = mid , l = mid + 1;
        else r = mid - 1;
    }
    cout << res << "\n";



}

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

C. Non-coprime Split

只要区间中有大于 2 的偶数一定可以,对于区间内只有奇数的情况就暴力的判一下。

#include <bits/stdc++.h>

using namespace std;

#define int long long

constexpr int mod = 1e9 + 7, inf = 1e18;
using i64 = long long;
using pii = pair<int, int>;

void solve() {
    int l, r;
    cin >> l >> r;
    if (r <= 3) return cout << "-1\n", void();
    if (l == r) {
        if (r % 2 == 0) {
            cout << 2 << " " << r - 2 << "\n";
            return;
        }
        for (int i = 2; i * i <= r; i++)
            if (r % i == 0) {
                cout << i << " " << r - i << "\n";
                return;
            }
        return cout << "-1\n", void();
    }
    if (r & 1) r--;
    cout << 2 << " " << r - 2 << "\n";
    return;
}

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

D. Plus Minus Permutation

算出来最多能取多少个数字,贪心的取最大的即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve(){
    int n , a , b , c;
    cin >> n >> a >> b ;
    c = lcm( a , b );
    a = n / a , b = n / b , c = n / c;
    a -= c , b -= c;
    int res = ( 2 * n - a + 1 ) * a / 2 - b * ( 1 + b ) / 2;
    cout << res << "\n";
    return ;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for( cin >> TC ; TC ; TC --)
        solve();
    return 0;
}

E. Data Structures Fan

看到比较懂 DS 的佬是线段树写的。我的做法是前缀异或和,求区间取反操作就直接把这一段直接异或到答案上即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve(){
    int n , res = 0;
    cin >> n;
    vector<int> a(n+1);
    for( int i = 1 ; i <= n ; i ++ )
        cin >> a[i];
    string s;
    cin >> s;
    for( int i = 1 ; i <= n ; i ++ )
        if( s[i-1] == '1' ) res ^= a[i];
    for( int i = 2 ; i <= n ; i ++ )
        a[i] ^= a[i-1];
    int q;
    cin >> q;
    for( int op , x , y ; q ; q -- ){
        cin >> op >> x;
        if( op == 1 ){
            cin >> y;
            res ^= (a[y] ^ a[x-1]);
        }else {
            if( x == 1 ) cout << res << " ";
            else cout << ( res ^ a[n] ) << " ";
        }
    }
    cout << "\n";
    return ;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for( cin >> TC ; TC ; TC --)
        solve();
    return 0;
}

F. Selling a Menagerie

这个图本身是一个内向基环树森林,所以除了每一颗基环树,只有环上的一个点无法取到两倍贡献,自然这个点就是权值最小的点,所以我们找到每一个环上的这个点,然后删掉他对应的边,最后求一下拓扑序就是答案。

#include <bits/stdc++.h>

using namespace std;

#define int long long

constexpr int mod = 1e9 + 7, inf = 1e18;
using i64 = long long;
using pii = pair<int, int>;

void solve() {
    int n, it;
    cin >> n;
    vector<int> a(n + 1), vis(n + 1), c(n + 1), inner(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> c[i];

    auto dfs = [&it, &vis, a, c, n](auto &&self, int x, int tag) -> void {
        if (vis[x] == 0) vis[x] = tag;
        else if (vis[x] == tag) {
            if (it == 0 or c[x] < c[it]) it = x;
            vis[x] = tag + n;
        } else return;
        self(self, a[x], tag);
    };
    for (int i = 1; i <= n; i++) {
        if (vis[i]) continue;
        it = 0, dfs(dfs, i, i), a[it] = 0;
    }
    for (int i = 1; i <= n; i++)
        if (a[i]) inner[a[i]]++;

    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (inner[i] == 0) q.push(i);
    for (int x; !q.empty();) {
        x = q.front(), q.pop();
        cout << x << " ";
        x = a[x];
        if (x == 0) continue;
        if (--inner[x] == 0) q.push(x);
    }
    cout << "\n";
    return;
}

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

G. Replace With Product

有几个特殊的性质,前缀后缀的1一定不会被选。其次 1 一定不会做端点,所以我们可以先判断一下,去掉前缀后乘积是否大于和,大于就可以直接输出答案。否则的话,我们枚举非1的点最为端点,然后计算一下即可。为了快速计算,可以提前处理前缀和前缀积。

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;
using i128 = __int128;
using pii = pair<int, int>;
constexpr int mod = 1e9 + 7, inf = 1e18;
constexpr i128 lim = 1e15;

void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    int l = 1, r = n;
    while (l <= r and a[l] == 1) l++;
    while (l <= r and a[r] == 1) r--;
    if (l > r) {
        cout << "1 1\n";
        return;
    }
    bool flag = false;
    i128 mul = 1;
    for (int i = 1; i <= n and flag == false; i++){
        if (mul * (i128)a[i] > lim) flag = true;
        mul *= (i128)a[i];
    }
    if (flag) {
        cout << l << " " << r << "\n";
        return;
    }
    vector<int> s1(n + 1), s2(n + 1), can;
    s2[0] = 1;
    for (int i = 1; i <= n; i++) {
        s1[i] = s1[i - 1] + a[i];
        s2[i] = s2[i - 1] * a[i];
        if (a[i] > 1) can.push_back(i);
    }
    int ans = s1[n];
    pii res = make_pair(1, 1);
    for (auto i: can)
        for (auto j: can) {
            if (j > i) break;
            int t = s2[i] / s2[j - 1] + s1[n] - s1[i] + s1[j - 1];
            if (t > ans) ans = t, res = make_pair(j, i);
        }
    cout << res.first << " " << res.second << "\n";
    return;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}
posted @ 2023-09-10 20:40  PHarr  阅读(55)  评论(0编辑  收藏  举报