Educational Codeforces Round 188 (Rated for Div. 2)

A. Passing the Ball

纯模拟的,但好像是找第一个 L 的位置就行

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
    int n;
    cin>>n;
    string s;
    cin>>s;
    s=" "+s;

    vector<int> st(n+1);

    int now=1;
    st[1]=1;
    for(int i=2;i<=n;i++){
        if(s[now]=='R'){
            now++;
            st[now]=1;
        }
        else{
            now--;
            st[now]=1;
        }
    }

    int ans=0;
    for(int i=1;i<=n;i++){
        if(st[i]) ans++;
    }
    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;

    while(ct--){
        solve();
    }
}

B. Right Maximum

直接 ST 表草过去了,火箭毛毛虫

实际好像是找所有前缀最大值的位置就行(?

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

struct ST {
    int n;
    vector<int> in1, in2, lg;
    vector<vector<int>> Max, Min;
    ST(int n) : n(n), in1(n + 1), in2(n + 1), lg(n + 1) {
        for (int i = 2; i <= n; i++) {
            lg[i] = lg[i / 2] + 1;
        }
        Max.resize(n + 1, vector<int>(lg[n] + 1));
        Min.resize(n + 1, vector<int>(lg[n] + 1));
    }
    void init() {
        for (int i = 1; i <= n; i++) {
            Max[i][0] = in1[i];
            Min[i][0] = in2[i];
        }
        int k = lg[n];
        for (int j = 1; j <= k; j++) {
            for (int i = 1; i + (1 << j) - 1 <= n; i++) {
                Max[i][j] = max(Max[i][j - 1], Max[i + (1 << (j - 1))][j - 1]);
                Min[i][j] = min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
    int getMax(int l, int r) {
        if (l > r) {
            swap(l, r);
        }
        int k = lg[r - l + 1];
        return max(Max[l][k], Max[r - (1 << k) + 1][k]);
    }
    int getMin(int l, int r) {
        if (l > r) {
            swap(l, r);
        }
        int k = lg[r - l + 1];
        return min(Min[l][k], Min[r - (1 << k) + 1][k]);
    }
};

void solve(){
    int n;
    cin>>n;

    ST st(n);
    vector<vector<int>> pos(n+1);

    for(int i=1;i<=n;i++){
        cin>>st.in1[i];
        pos[st.in1[i]].push_back(i);
    }

    st.init();

    int l=1,r=n;
    int ans=0;

    while(l<=r){
        int mx=st.getMax(l,r);
        ans++;

        while(pos[mx].back()>r){
            pos[mx].pop_back();
        }

        // cout<<mx<<" "<<pos[mx].back()<<endl;

        r=pos[mx].back()-1;
        pos[mx].pop_back();
        // cout<<r<<endl;
    }

    cout<<ans<<endl;

}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;

    while(ct--){
        solve();
    }
}

C. Spring

纯纯小学数学题

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;


void solve(){
    int a,b,c,m;
    cin>>a>>b>>c>>m;

    auto f=[&](int t1,int t2,int t3)-> int {
        int ans=m/t1*6;
        ans-=m/lcm(t1,t2)*3;
        ans-=m/lcm(t1,t3)*3;
        ans+=m/lcm(t1,lcm(t2,t3))*2;
        return ans;
    };

    // f(a,b,c);
    cout<<f(a,b,c)<<" "<<f(b,a,c)<<" "<<f(c,b,a)<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;

    while(ct--){
        solve();
    }
}

D. Alternating Path

首先,如果存在奇环,这个环上的点一定不行。

因为题目中定义,如果一个点是美丽的,则这个点出去的所有路径都得是符合题意的。所以,这要这个点,能碰到奇环,就一定不行

所以对只要能被奇环联通的点,就一定不行

所以只需要对每个联通块判断是否存在奇环即可

染色法判奇环(存在奇环是 不是二分图 的充要条件,所以更普遍的叫法是染色法判定二分图)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
    int n,m;
    cin>>n>>m;

    vector<vector<int>> g(n+1);
    vector<int> c(n+1,-1);

    while(m--){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    int ans=0;
    for(int i=1;i<=n;i++){
        if(c[i]!=-1) continue;

        queue<int> q;
        q.push(i);
        c[i]=0;
        int c0=1,c1=0,f=1;

        while(q.size()){
            int u=q.front();
            q.pop();

            for(auto v:g[u]){
                if(c[v]==-1){
                    c[v]=c[u]^1;
                    if(c[v]==1) c1++;
                    else c0++;
                    q.push(v);
                }
                else if(c[v]==c[u]){
                    f=0;
                }
            }
        }

        if(f){
            ans+=max(c1,c0);
        }
    }

    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;

    while(ct--){
        solve();
    }
}

E. Sum of Digits (and Again)

一共有 \(1e5\) 个数字,则数位和最大值也是 \(9e5\)

所以第二个数字一定是小于 \(9e5\)

枚举第二个数字即可,需要处理出,从第二个数字开始,后续的所有数位和,后续的每个数字消耗了多少个

对于每个字符串,直接 \(O(9*n)\) 的去枚举可能的第二个数字即可

赛时算错复杂度了,为了降复杂度写了个很抽象的类似哈希的东西,下面的代码是赛后补的

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

const int N=9e5+1;
/**
 * 以 i 作为字符串中第二个出现的数字时
 * 例:xxxxx,99999,45,9
 * 
 * cnt:从 99999 开始,后面所有数位的计数
 * sum:从 99999 开始,后面所有数位的和
 */
vector cnt(N,vector<int>(10));
vector<int> sum(N);

void init(){
    for(int i=1;i<N;i++){
        int val=i;
        while(val){
            cnt[i][val%10]++;
            sum[i]+=val%10;
            val/=10;
        }
        if(i>9){
            val=sum[i];
            for(int j=0;j<=9;j++){
                cnt[i][j]+=cnt[sum[i]][j];
            }
            sum[i]+=sum[sum[i]];
        }
    }
}

void solve(){
    string s;
    cin>>s;

    if(s.size()==1){
        cout<<s<<endl;
        return;
    }
    vector<int> c(10);
    int t=0;
    
    for(auto ch:s){
        t+=ch-'0';
        c[ch-'0']++;
    }

    auto check=[&](int val)->bool {
        if(t-sum[val]!=val) return 0;
        for(int i=0;i<=9;i++){
            if(c[i]<cnt[val][i]) return 0;
        }
        return 1;
    };

    for(int i=1;i<=9*s.size();i++){
        if(check(i)){
            for(int j=0;j<=9;j++){
                c[j]-=cnt[i][j];
            }

            for(int j=9;j>=0;j--){
                for(int k=1;k<=c[j];k++){
                    cout<<j;
                }
            }
            cout<<i;
            int now=i;
            while(now>9){
                int tmp=0;
                while(now){
                    tmp+=now%10;
                    now/=10;
                }
                cout<<tmp;
                now=tmp;
            }
            cout<<endl;
            return;
            
        }
    }


}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    init();

    int ct=1;
    cin>>ct;

    while(ct--){
        solve();
    }
}
posted @ 2026-03-17 17:57  LYET  阅读(1)  评论(0)    收藏  举报