Codeforces Round #819 (Div. 1 + Div. 2) A -D

Dashboard - Codeforces Round #819 (Div. 1 + Div. 2) and Grimoire of Code Annual Contest 2022 - Codeforcesicon-default.png?t=M85Bhttps://codeforces.com/contest/1726

A. Mainak and Array

第一种是不动第一个,那自然是2-n的最大值减第一个

第二种是不动最后一个,那自然是n减1-n-1的最小值

第三种是都动,那自然是相邻的差值

取所有可能的最大值即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int maxn = 2e6+10;
const int mod = 1e9+7;

int num[maxn];

void solve(){
    int n;
    cin>>n;
    for(int i = 1;i<=n;i++){
        cin>>num[i];
    }
    int cnt = 0;
    for(int i = 1;i<=n;i++){
        if(i==n)
            cnt = max(cnt,num[n]-num[1]);
        else
            cnt = max(cnt,num[i]-num[i+1]);
    }
    for(int i = 1;i<n;i++){
        cnt = max(cnt,num[n]-num[i]);
    }
    for(int i = 2;i<=n;i++){
        cnt = max(cnt,num[i]-num[1]);
    }
    cout<<cnt<<endl;
}

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

B. Mainak and Interesting Sequence‘

构造题。

我们可以针对n是奇数或者偶数情况进行构造

n如果是奇数其实是最好构造的,n-1部分赋值成1,然后n是剩下的部分

n如果是偶数要分两种情况,一种是m是奇数的情况,这种是NO,m是偶数就可以构造n-2个1,然后剩下的平分即可。

假设排序好后为a1....a1(共num个) ,a2。对a2而言,a1一定要是具备偶数个的,否则对a2而言p值就不会为0了。而偶数个a1贡献出的sum也是偶数,到最后m无法平分,因此是不行的。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int maxn = 2e6+10;
const int mod = 1e9+7;

int num[maxn];

void solve(){
   int n,m;
   cin>>n>>m;
   if(n>m){
       cout<<"NO"<<endl;
       return;
   }
   if(m%2==1&&n%2==0){
       cout<<"NO"<<endl;
       return;
   }
   cout<<"YES"<<endl;
   if(n%2==1){
       for(int i = 1;i<n;i++)
           cout<<1<<" ";
       cout<<m-n+1<<endl;
   }
   else{
       for(int i =1;i<n-1;i++)
           cout<<1<<" ";
       cout<<(m-n+2)/2<<" "<<(m-n+2)/2<<endl;
   }
}

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

C. Jatayu's Balanced Bracket Sequence

问有几个连通块,但是由于左括号和右括号是一定连通的,所以其实可以转化成左括号彼此之间是否连通的问题。

我们经过观察可以得知只有出现并列才会产生新的连通块

((()))像这样三个左括号并不会产生新的连通

但是如果是(()())这样 第二个左括号和第三个左括号会产生连通,即包含关系不会连通,而并列关系会连通。

在一个合法的括号序列中,并列关系的个数是夹杂在所有左括号中的右括号

或者是左右括号相邻 s[i]=='(’&&s[i+1] == ')' 的个数

算出来产生新联通的个数用n减去即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int maxn = 1e6+10;
const int mod = 1e9+7;



int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t = 1;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        string s;
        cin>>s;
        int ans = n;
        int cnt = n;
        int j = 0;
        for(int i = 0;i<s.size();i++){
            if(s[i]=='('){
                j = 1;
                cnt--;
                if(!cnt)
                    break;
            }
            if(j&&s[i]==')'){
                j = 0;
                ans--;
            }
        }
        cout<<ans<<endl;
    }
}

D. Edge Split

完全没有思路的题=-=

感觉比较好的题解大概是这个意思。对于每一条边而言,在不考虑成环情况下,它能让连通块整数-1,但是如果成环了那么这条边就木大了。

分红蓝线又要让C1+C2最小,其实就是让红不成环,蓝也不成环。

同时要注意m<=n+2这一条件,我们可以考虑最小生成树的概念(已知整张图是连通的),我们可以确定n-1条边不成环并标上红色,那么最多剩下3条边,如果成环只有三元环的情况,我们将其中一条边v改成红色。

同时改了以后红色出现环,我们将v的一个端点的所有边改成蓝色就可以去掉环了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int maxn = 1e6+10;


int a[maxn],b[maxn];

int f[maxn];

int find(int x){
    if(f[x]==x)
        return x;
    return f[x] = find(f[x]);
}

int same(int x,int y){
    if(find(x)==find(y)){
        return 1;
    }
    return 0;
}

int merge(int x,int y){
    if(same(x,y))
        return 0;
    f[find(x)] = find(y);
    return 1;
}
pair<int,int>p[maxn];
void solve(){
    int n,m;
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
        f[i] = i;
    }
    int s,e;
    vector<vector<pair<int,int>>>v(n+1);
    vector<int>ans(m+1);
    for(int i = 1;i<=m;i++)
        ans[i] = 1;
    for(int i = 1;i<=m;i++){
        cin>>s>>e;
        p[i] = {s,e};
        if(merge(s,e)){
            v[s].push_back({e,i});
            v[e].push_back({s,i});
        }
        else
            ans[i] = 0;  //不在最小生成树内
    }
    if(n+2==m){
        set<int>ss;
        int now = 0;
        for(int i = 1;i<=m;i++){
            if(!ans[i]){
                ss.insert(p[i].first);
                ss.insert(p[i].second);
                now = i;
            }
        }
        if(ss.size()==3){//说明是三元环
            ans[now] = 1; //标红
            int point = p[now].first; //一个端点
            for(auto i:v[point]){
                ans[i.second] = 0;
            }
            for(int i = 1;i<=m;i++){
                cout<<ans[i];
            }
            cout<<endl;
        }
        else{
            for(int i = 1;i<=m;i++){
                cout<<ans[i];
            }
            cout<<endl;
        }
    }//可能三元环
    else{
        for(int i = 1;i<=m;i++){
            cout<<ans[i];
        }
        cout<<endl;
    }
}

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

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值