Educational Codeforces Round 55 (Rated for Div. 2)

A. Vasya and Book

分情况讨论,当x大于y的时,交换x,y是错误的!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;

int t;
int n,d,x,y;

int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d",&n,&x,&y,&d);
        int t=abs(x-y);
        if(t%d==0)printf("%d\n",t/d);
        else if(y==1)printf("%d\n",(x-2)/d+1);
        else if(y==n)printf("%d\n",(y-x-1)/d+1);
        else {
            int ans=inf;
            if((y-1)%d==0)ans=min(ans,(y-1)/d+(x-2)/d+1);
            if((n-y)%d==0)ans=min(ans,(n-y)/d+(n-x-1)/d+1);
            printf("%d\n",ans!=inf?ans:-1);
        }
    }

    return 0;
}

B. Vova and Trophies

统计出有num个G串,第i个G串的数量为cnt[i]。
第i个G串能否和下一个G串链接,用can[i]表示。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max_n=1e5+10;

int n;
char s[Max_n];
int cnt[Max_n];
bool can[Max_n];

int main()
{
    scanf("%d%s",&n,s);
    int num=0;
    memset(cnt,0,sizeof(cnt));
    memset(can,0,sizeof(can));
    for(int i=0;i<n;i++){
        if(s[i]=='G'){
            if(i>0&&s[i-1]=='G')cnt[num]++;
            else cnt[++num]++;
        }
        else {
            if(i>0&&i<n-1&&s[i-1]=='G'&&s[i+1]=='G')
                can[num]=true;
        }
    }
    int Max=0;
    for(int i=1;i<=num;i++){
        if(can[i]){
            if(i>1||i+1<num)Max=max(Max,cnt[i]+cnt[i+1]+1);
            else Max=max(Max,cnt[i]+cnt[i+1]);
        }
        else {
            if(i>1||i<num)Max=max(Max,cnt[i]+1);
            else Max=max(Max,cnt[i]);
        }
    }
    printf("%d\n",Max);
    return 0;
}

// 另附录网上大佬代码,膜拜!

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n; string s;
    //freopen("in.txt","r",stdin);
    while(cin>>n){
        cin>>s;
        int cntG=0,cntS=0,sumG=0,ans=0;
        for(int i=0;i<n;i++){
            if(s[i]=='G'){
                cntG++; sumG++;
            }
            else{
                cntS=cntG; cntG=0;//遇到scntG从新归零统计G连续的个数 
            }
            ans=max(ans,cntG+cntS+1);//假设都可以交换带来收益 
        }
        ans=min(ans,sumG);//这里很关键存在交换没有带来收益的 
        cout<<ans<<endl;
    }
    return 0;
}

C. Multi-Subject Competition

先以选科目总数降序排序,其次以科目升序排序,最后以能力水平降序排序。
然后两层for循环暴力枚举。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max_n=1e5+10;

int n,m;
struct node{
    int s,r,k; //k代表选s科目的总人数
    bool operator<(const node &n)const {
        if(k!=n.k)return k>n.k;
        if(s!=n.s)return s<n.s;
        return r>n.r;
    }
}no[Max_n];
int sum[Max_n]; //前缀和
int cnt[Max_n]; //第i个科目的人数

int main()
{
    scanf("%d%d",&n,&m);
    memset(cnt,0,sizeof(cnt));
    no[0].s=no[0].r=0;no[0].k=Max_n;
    for(int i=1;i<=n;i++){
        scanf("%d%d",&no[i].s,&no[i].r);
        cnt[no[i].s]++;
    }
    for(int i=1;i<=n;i++){
        no[i].k=cnt[no[i].s];
    }
    sort(no,no+n+1);
    //for(int i=0;i<=n;i++)cout<<no[i].s<<' '<<no[i].r<<' '<<no[i].k<<endl;
    for(int i=1;i<=n;i++){
        sum[i]+=sum[i-1]+no[i].r;
    }
    int Max=0;
    for(int i=1;i<=n;i++){ //最多n个人同时选一个科目
        int ans=0;
        for(int j=1;j<=n;j+=no[j].k){
            if(no[j].k<i)break; //选第no[j].s科目人数小于i
            if(sum[j+i-1]-sum[j-1]>0)
                ans+=sum[j+i-1]-sum[j-1];
        }
        if(ans>Max)Max=ans;
    }
    printf("%d\n",Max);
    return 0;
}

// 另附网上大佬代码,膜拜!
首先,读入后,把每一个分数扔进相应学科的桶。
然后贪心地对每个桶排序。
然后对于每一个桶,求前缀和,如果大于0,就加到对应的sum[i]中(sum[i]记录的是每个学科i个人的最大得分)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int Max_n=1e5+10;

int n,m;
int sum[Max_n];
vector<int>v[Max_n];

int main()
{
    scanf("%d%d",&n,&m);
    int a,b;
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a,&b);
        v[a].push_back(b);
    }
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=m;i++){
        sort(v[i].begin(),v[i].end(),greater<int>());
        int tmp=0;
        for(int j=0;j<v[i].size();j++){
            tmp+=v[i][j];
            if(tmp<0)break;
            sum[j+1]+=tmp;
        }
    }
    int Max=0;
    for(int i=1;i<=n;i++){
        Max=max(sum[i],Max);
    }
    printf("%d\n",Max);
    return 0;
}

D. Maximum Diameter Graph

写了很久,感觉思路蛮对的,一直WA18…看了好几天,终于A了,开心!
定义: 1. 主干长度:所有入度>1的顶点数排成一排。 2. 入度为1的点为叶子。
最长路径=主干长度+是否能在主干两端各加一个叶子(想一想,很简单的)
// 输出路径时,先输出主干路径,再在两端各加一个叶子达到最长(可以的话),最后,剩余的叶子随意加到主干上就好。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max_n=5500;

int n;
int s[Max_n];
int x=0,a[Max_n]; //入度>1顶点数
int y=0,b[Max_n]; //入度=1顶点数

int main()
{
    scanf("%d",&n);
    int sum=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        if(s[i]>1){sum+=s[i];a[x++]=i;}
        else b[y++]=i;
    }
    
    //判断输出YES条件:sum-(x-1)*2>=y
    //最长路径=主干长度(所有入度>1顶点数)+是否能在主干两端各加一个叶子
    if(sum-(x-1)*2>=y)printf("YES %d\n%d\n",x-1+(y>1?2:y),n-1);
    else {printf("NO\n");return 0;}
    
    //输出主干路径
    for(int i=1;i<x;i++)
        printf("%d %d\n",a[i-1],a[i]);
    if(y>=1)printf("%d %d\n",b[0],a[0]); //必须先在主干两端加叶子!
    if(y>=2)printf("%d %d\n",b[1],a[x-1]);
    //剩下的入度=1顶点数随意加在主干上
    int i=2,j=0;
    while(i<y){
        if(s[a[j]]>2){
            printf("%d %d\n",b[i],a[j]);
            s[a[j]]--;i++;
        }
        else j++;
    }
    return 0;
}

// 附上自测样例:

8
4 2 3 1 1 1 1 1
YES 4
7
1 2
2 3
4 1
5 3
6 1
7 1
8 3

5
4 2 3 1 1
YES 4
4
1 2
2 3
4 1
5 3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值