其他分享
首页 > 其他分享> > Codeforces Round #797 (Div. 3)

Codeforces Round #797 (Div. 3)

作者:互联网

Codeforces Round #797 (Div. 3)

感觉这场div3要简单许多,不过还是没ak···。

ABC略,从D开始吧

D

题意:

给一个“BW” 串,问至少几次修改,能构成一个长度为 \(k\) 的连续的 “B”。

思路:

暴力把 \([1,k]\) 的串操作次数算了,之后向右滑动,只用计算最左边滑出的和最右边新加入的字符产生的贡献就行。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;

void solve()
{    
    int n,k; cin >> n >> k;
    string s; cin >> s;
    s = ' ' + s;
    int ans = 0;
    rep(i,1,k) if(s[i] == 'W') ans ++;
    int res = ans;
    rep(i,2,n - k + 1) {
        if(s[i - 1] == s[i + k - 1]) continue;
        if(s[i - 1] == 'W') ans -= 1;
        if(s[i - 1] == 'B') ans += 1;
        res = min(ans, res);
    }
    cout << res << endl;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}

E

题意:

给一堆数两两配对,每个数对的贡献是 \(\lfloor \frac{a + b}{k} \rfloor\) 。 \(k\) 已知,最大化贡献和

思路:

考虑什么时候更优,发现余数会完全浪费掉,所以明确贪心策略,尽可能让数对的余数为0。场上写的时候没注意,写了一版纯纯的暴力,但竟然能ACΣ(っ °Д °;)っ。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;

void solve()
{    
    int n,k; cin >> n >> k;
    vector<int> a(n + 1);
    rep(i,1,n) cin >> a[i];
    set<int> s[k + 1];
    rep(i,1,n) s[a[i] % k].insert(i);
    int ans = 0;
    vector<bool> st(n + 1);
    rep(i,1,n) if(!st[i]) {
        int x = a[i];
        st[i] = 1;
        s[x % k].erase(i);
        int r1 = k - x % k;
        if(s[r1].size()) {
            int p = *s[r1].begin();
            s[r1].erase(s[r1].begin());
            st[p] = 1;
            x += a[p];
            ans += x / k;
            continue;
        }
        int r = x % k;
        int r2 = r;
        int mn = inf;
        rep(j,0,k - 1) {
            if(s[j].size()) {
                if((r + j) % k < mn) {
                    mn = (r + j) % k;
                    r2 = j;
                }
            }
        }
        int p = *s[r2].begin();
        s[r2].erase(s[r2].begin());
        st[p] = 1;
        x += a[p];
        ans += x / k;
    }
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}

赛后感觉时间复杂度不太对,又想了想,其实每一个余数为0的数对,都可以对答案有 \(1\) 的额外贡献,其余的余数因为凑不到 \(k\) 被舍去了了,所以匹配一下余数为0就行,这个过程可以对一个余数set二分。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;

void solve()
{    
    int n,k; cin >> n >> k;
    vector<int> a(n + 1);
    rep(i,1,n) cin >> a[i];
    multiset<int> s;
    int ans = 0;
    rep(i,1,n) {
        ans += a[i] / k;
        s.insert(a[i] % k);
    }
    while(s.size()) {
        int x = *s.begin();
        s.erase(s.begin());
        auto it = s.lower_bound(k - x);
        if(it != s.end()) {
            s.erase(it);
            ans ++;
        }
    }
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}

F

题意:

给一个字符串 \(s\) ,和一个排列 \(p\)。用 \(p\) 对 \(s\) 不断做变换,问至少几次可以重新变成 \(s\) 。

思路

看到是用排列做一些判断,就想到应该是在置换环上做一些事情,可以发现,当每个环中元素不同时,要想重新变回去,就要让所有环在同一时刻回到初始状态,也就是求他们的\(lcm\)。当环中的元素有循环节时,可以发现,这个环回到初始状态的被提前了。

因此对每个环,找循环节,得到贡献,对每个贡献求lcm就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;

void solve()
{    
    int n; cin >> n;
    string s; cin >> s;
    vector<int> a(n + 1);
    rep(i,1,n) cin >> a[i];
    vector<bool> st(n + 1);
    s = ' ' + s;
    int ans = 1;
    rep(i,1,n) if(!st[i]){
        string t;
        int p = i;
        do {
            st[p] = 1;
            t += s[p];
            p = a[p];
        }while(!st[p]);
        int cnt = 0;
        int m = t.size();
        rep(j,1,min(m,n)) {
            bool ok = 1;
            rep(k,0,m - 1) {
                if(t[k] != t[(k + j) % m]) {
                    ok = 0;
                    break;
                }
            }
            if(ok) {
                cnt = j;
                break;
            }
        }
        // cout << t << " " << cnt << endl;
        ans = lcm(ans, cnt);
    }
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}

G

题意

有很多车厢,每个车厢都有一个最快速度 \(a_i\) ,现在让这些车都向左开,保证在不碰撞的情况下尽可能快。最后速度相同的看成一列列车。

比如 ,\([10,4,5,2,1]\) ,变成 \([10,4,4,2,1]\) ,构成4列列车

共 \(m\) 次询问,每次修改一个 \(a_i := a_i - d\) 。问能构成列车的数量。

思路

首先,发现这个序列中很多值是没有贡献的,有贡献的只有那些能保证单调性的值。也就是跑一遍单调栈,栈中能留下的前缀最小值们。

那么就有一个大概的想法,维护这些前缀最小值,在每次更新时,判断修改值能不能做一个新的前缀最小值。

按照这个想法,我们维护一个前缀最小值的set,当修改后,判断是否会成为一个新的前缀最小值,如果可以,再暴力把后缀中影响单调性的值删除。

时间复杂度,因为set中的值最多 \(n + m\) 种,并且只进行一次删除。所有大概是 \(O(mlog(n + m))\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;

void solve()
{    
    int n,m; cin >> n >> m;
    vector<int> a(n + 1);
    rep(i,1,n) cin >> a[i];
    int limit = a[1];
    set<int> s;
    s.insert(1);
    rep(i,2,n) {
        if(limit > a[i]) {
            s.insert(i);
            limit = a[i];
        }
    }
    
    rep(i,1,m) {
        int pos,x; cin >> pos >> x;
        a[pos] -= x;
        auto it = s.lower_bound(pos);
        if(it != s.begin()) it --;
        if(pos > 1 && a[*it] > a[pos]) s.insert(pos);
        it = s.upper_bound(pos);
        while(it != s.end()) {
            if(a[pos] <= a[*it]) it = s.erase(it);
            else break;
        }
        
        cout << s.size() << " ";
    }
    cout << endl;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}

标签:797,int,rep,Codeforces,long,ans,Div,include,define
来源: https://www.cnblogs.com/Mxrush/p/16357097.html