Codeforces Round 1026 (Div. 2) A-D,F

A. Fashionable Array

暴力即可

点击查看代码
#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;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

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

    sort(a.begin()+1,a.end());

    int ans=n-1;

    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            if((a[i]+a[j])%2 == 0){
                ans=min(ans,i-1+n-j);
            }
        }
    }
    cout<<ans<<endl;
}   

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

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

B. Down with Brackets

如果原序列能分成两个独立且合法的序列,则可以,否则No

点击查看代码
#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;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
    string s;
    cin>>s;
    int n=s.size();

    s=" "+s;
    vector<int> pre(n+10);
    for(int i=1;i<n;i++){
        if(s[i]=='(') pre[i]=1;
        else pre[i]=-1;
        pre[i]+=pre[i-1];
        if(pre[i]==0){
            cout<<"YES\n";
            return;
        }
    }

    cout<<"NO\n";
}   

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

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

C. Racing

先从前往后,计算每个区间的合法取值范围,再从后往前,看能否回到0点。

点击查看代码
#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;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

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

    vector<int> d(n+2),l(n+2),r(n+2);

    for(int i=1;i<=n;i++){
        cin>>d[i];
    }

    for(int i=1;i<=n;i++){
        cin>>l[i]>>r[i];
    }

    for(int i=1;i<=n;i++){
        if(d[i]==0){
            l[i]=max(l[i],l[i-1]);
            r[i]=min(r[i],r[i-1]);
        }
        else if(d[i]==1){
            l[i]=max(l[i],l[i-1]+1);
            r[i]=min(r[i],r[i-1]+1);
        }
        else{
            l[i]=max(l[i],l[i-1]);
            r[i]=min(r[i],r[i-1]+1);
        }
        if(l[i]>r[i]){
            cout<<-1<<endl;
            return;
        }
    }

    int now=l[n];


    for(int i=n;i>=1;i--){
        if(d[i]==1){
            now--;
        }
        else if(d[i]==-1){
            if(now>r[i-1]){
                now--;
                d[i]=1;   
            }else{
                d[i]=0;
            }
        }
    }
    if(now!=0){
        cout<<-1<<endl;
        return;
    }
    for(int i=1;i<=n;i++){
        cout<<d[i]<<" ";
    }
    cout<<endl;


}   

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

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

D. Fewer Batteries

二分答案,因为是拓扑图,且边只会从较小节点指向较大节点,所以check时for循环一遍即可

点击查看代码
#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;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

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

    vector<int> b(n+10);
    for(int i=1;i<=n;i++){
        cin>>b[i];
    }

    vector<vector<pii>> g(n+10);

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

    auto check = [&](int mid)-> bool {
        vector<int> dist(n+10,-1);
        dist[1]=min(b[1],mid);

        for(int i=1;i<=n;i++){
            if(dist[i]>inf/2) continue;
            for(auto [v,w]:g[i]){
                if(dist[i]<w) continue;
                dist[v]=min(mid,max(dist[v],dist[i]+b[v]));
            }
        }
        return dist[n]!=-1;
    };

    int l=1,r=1e9;
    while(l<r){
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }

    if(check(l)) cout<<l;
    else cout<<-1;

    cout<<endl;
}   

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

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}

F. Faculty

对于某一个前缀的xy,假设x<y

那么x%y + y%x = x + y%x <= x+y-x (当且仅当x<y && y<2*x)时,取等号

y一定是前缀最大值。

证明:假设x < z < y

x%z + z%x <= z <= z%y + y%z = z+y%z

所以y一定会选前缀最大值

所以当a[i]<=mx时,只需要尝试更新x即可

当a[i]>mx && a[i]<2*mx 时,x=mx, y=a[i]可以取到最大值。之后把mx更新成a[i]

当a[i]>=2*mx时,暴力的去前缀中重新找x。

因为每次*2,所以复杂度不超过log次。

点击查看代码
#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;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){   
    int n;
    cin>>n;
    vector<int> a(n+10),ans(n+10);

    for(int i=1;i<=n;i++){
        cin>>a[i];
    }

    int mx=a[1];

    for(int i=2;i<=n;i++){
        if(a[i]<=mx){
            ans[i]=max(ans[i-1],mx%a[i]+a[i]%mx);
        }
        else if(mx<a[i] && a[i]<2*mx){
            // int x=mx;
            mx=a[i];
            ans[i]=mx;
        }
        else{
            mx=a[i];
            for(int j=1;j<i;j++){
                ans[i]=max(ans[i], a[j]%mx + mx%a[j]);
            }
        }
    }

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

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

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }

    return 0; 
}
posted @ 2025-05-26 19:53  LYET  阅读(109)  评论(0)    收藏  举报