Educational Codeforces Round 145 (Rated for Div. 2)

发布时间 2023-04-03 19:49:49作者: PHarr

A. Garland

分类讨论

#include <bits/stdc++.h>

using namespace std;

void solve(){
    string s;
    cin >> s;
    map<char,int> cnt;
    for( auto c : s ) cnt[c]++;
    if( cnt.size() == 1 ){
        cout << "-1\n";
    }else if( cnt.size() > 2 ){
        cout << "4\n";
    } else {
        int t = cnt.begin()->second;
        if( t == 2 ) cout << "4\n";
        else cout << "6\n";
    }
}

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

B. Points on Plane

其实就是在防止的时候间隔一个位置就好。手推一下就能找到规律,注意如果放在距离原点偶数距离的位置上时原点也可以放一个

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}

int32_t main() {
    ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
    int t , n , l , r , res , mid ;
    t = read();
    auto f = []( int x ){
        if( x & 1 ) return (x+1)*(x+1);
        else return x * ( x + 2 ) + 1;
    };
    while( t -- ){
        n = read();
        l = 0 , r = 1e9;
        while( l <= r ){
            mid = ( l + r ) >> 1;
            if( f(mid) >= n ) res = mid , r = mid - 1;
            else l = mid + 1;
        }
        cout << res << "\n";
    }
    return 0;
}

C. Sum on Subarrays

首先找一段长度为\(t\)的区间全部填\(1\),剩余的地方全部都填\(-1000\),即\(1,1,\cdots,1,-1000,-1000\cdots\)

此时,整数区间就是\(\frac{t(t+1)}{2}\),我们求出最大的\(t\)满足\(\frac{t(t+1)}{2}\le k\),此时剩下的所需区间数一定小于\(t\)

因为

\[\frac{t(t+1)}{2}\le k \le \frac{(t+1)(t+2)}{2}-1\\ 0\le k - \frac{t(t+1)}{2}\le \frac{(t+1)(t+2)}{2}-1-\frac{t(t+1)}{2}=t \]

如果还缺少\(x\)个元素,就把第一个\(-1000\)变成\(k-t-1\),这里的\(k\)是剩下的所需要区间,然后把\(x\)\(1\)变的大一些(\(500\)就行),满足前\(x\)个元素做左端点,\(k-t-1\)做右端点,恰好有\(x\)个区间是求和是正数。

#include<bits/stdc++.h>

using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

void solve() {
    int n = read(), k = read();
    vector<int> a(n, -1000);
    int l = 0, r = n, mid, t;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (mid * (mid + 1) / 2 <= k) t = mid, l = mid + 1;
        else r = mid - 1;
    }
    k -= t * (t + 1) / 2;
    for (int i = 0; i < t; i++) a[i] = 1;
    if( k ) a[k-1] = 500 , a[t] = k - t - 1;
    for( int i : a ) printf("%d " , i);
    printf("\n");
}

int main() {
    for (int t = read(); t; t--)
        solve();
    return 0;
}

D. Binary String Sorting

设状态为\(f[i][0/1/2]\)分别表示前i位,结尾没有 1、结尾一个 1、结尾多个 1 的最小代价。

很容易想到多次的交换是一定不如删除更优的,因此可以大大的简化转移方程。

#include<bits/stdc++.h>

using namespace std;

#define int long long

const int INF = 1e18, c1 = 1e12, c2 = c1 + 1;
// c1 swap , c2 remove

void solve() {
    string s;
    cin >> s;
    int n = s.size();
    vector<vector<int>> f(n + 1, vector<int>(3, INF));
    f[0][0] = 0;
    for (int i = 1; i <= n; i++) {
        if (s[i - 1] == '1') {
            f[i][0] = f[i - 1][0] + c2;
            f[i][1] = f[i - 1][0];
            f[i][2] = min(f[i - 1][1], f[i - 1][2]);
        } else {
            f[i][0] = f[i - 1][0];
            f[i][1] = f[i - 1][1] + c1;
            f[i][2] = f[i - 1][2] + c2;
        }
    }
    cout << *min_element( f[n].begin() , f[n].end() ) << "\n";
    return;
}

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