Codeforces Round #621 (Div. 1 + Div. 2)

Posted jjl0229

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #621 (Div. 1 + Div. 2)相关的知识,希望对你有一定的参考价值。

A. Cow and Haybales

题意:
有n堆草,每堆为ai,每分钟一次可以移动1个草从x到x-1或x+1。求在d分钟内,可以将第一堆的a1最大增加到多少。

思路:
从右2,3..依次枚举,要考虑距离以及是移动的最后一堆能移多少

代码:

#include<bits/stdc++.h>
using namespace std;
int a[101];
int main(){
    int n,d,T;
    cin>>T;
    while(T--){
        cin>>n>>d;
        for(int i=1;i<=n;++i)
            cin>>a[i];
        for(int i=2;i<=n;++i){
            if(d>(i-1)*a[i]){
                d-=(i-1)*a[i];
                a[1]+=a[i];
            }
            else {
                a[1]+=d/(i-1);
                break;
            }
        }
        cout<<a[1]<<endl;
    }
    return 0;
}

?

B. Cow and Friend

题意:
在二维平面上Bessie在(0,0)的位置要到达(x,0),一次可以k个移动确定的距离a1,a2...ak。

思路:
先移动选择最大的距离,当第i要再走一步会超过x时,考虑在i-1 和 i步的时候走一个等腰三角形,因为这样可以构造出一个(0,2a]的任意距离。我的代码考虑了判断是否存在a可以一步正好到达(其实没啥用,和走等腰的答案一样)

代码:

#include<bits/stdc++.h>
using namespace std;
int step[100010];
map<int,int> mmp;
void solve(){
    int n,x;
    mmp.clear();
    cin>>n>>x;
    int f=0;
    int Ms=0;
    for(int i=1;i<=n;++i){
        cin>>step[i];
        if(step[i]==x) {
            f=-1;
        }
        Ms=max(Ms,step[i]);
        mmp[step[i]]=1;
    }
    if(f==-1) {
        puts("1");
        return ;
    }
    int res=x/Ms;
    if(x%Ms==0){
    }
    else if(mmp[x%Ms]){
        res++;
    }
    else if(res>0){
        res+=1;
    }
    else
        res+=2;
    cout<<res<<'
';
}
int main(){
    int T;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

?

C. Cow and Message

题意:
给出一个字符串,求出所有的序列号为等差数列的一样的子序列的最多的数量。
例如“aaabb”,它可以按条件得到的子序列有:
a 构造方法有: (1), (2), (3)
b 构造方法有: (4), (5)
ab 构造方法有: (1,4), (1,5), (2,4), (2,5), (3,4), (3,5)
aa 构造方法有: (1,2), (1,3), (2,3)
bb 构造方法有: (4,5)
aab 构造方法有: (1,3,5), (2,3,4)
aaa 构造方法有: (1,2,3)
abb 构造方法有: (3,4,5)
aaab 构造方法有: (1,2,3,4)
aabb 构造方法有: (2,3,4,5)
aaabb 构造方法有: (1,2,3,4,5)
答案为6 ,即ab构造方法最多。

做法:可以举个例子:abc,构造ab的方法一定是大于或者等于构造abc的方法,因为构造abc会多产生了一个限制条件即c。所以我们只用考虑长度为1和2的子序列。

#include<bits/stdc++.h>
using namespace std;
char s[100010];
long long pre[30];
long long dp[30][30];
int main(){
    long long ans=0;
    cin>>s;
    for(int i=0;s[i];++i){
        for(char ch='a';ch<='z';++ch){
            dp[ch-'a'][s[i]-'a']+=pre[ch-'a'];
            ans=max(dp[ch-'a'][s[i]-'a'],ans);
        }
        pre[s[i]-'a']++;
        ans=max(ans,pre[s[i]-'a']);
    }
    cout<<ans<<'
';
    return 0;
}

?

D. Cow and Fields

题意:
在n个点m条边的无向图中给出k个特殊点,必须在
这k个点之间添加一条边,求如何添加得1-n的最短距离最大。

做法:很容易想到开两个数组跑两遍最短路算法,分别求每个点到1和n的最短距离。找到最大的ds[u]+dt[v]+1。然后需要考虑一个关键的限制性条件,我们选取的u,v首先满足ds[u]+dt[v]<=ds[v]+dt[u],再变换一下就是ds[u]-dt[u]<=ds[v]-dt[v]。首先我们要找的最大ds[u],且v一定是ds-dt大于u的,所以我们可以按ds-dt排个序,这样我们先选取ds[u]最大的u,后面的v一定符合条件,通过这样迭代找到ds[u]+dt[v]最大的。最后和原来的最短路做比较。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int head[maxn],cnt;
struct ac{
    int v,nex;
}edges[maxn*2];
void addedge(int u,int v){
    edges[++cnt]=(ac){v,head[u]};
    head[u]=cnt;
}
int a[maxn];
long long ds[maxn],dt[maxn];
bool inq[maxn];
void spfa(int st,long long dis[]){
    memset(inq,0,sizeof inq);
    queue<int> q;
    q.push(st);
    dis[st]=0;
    inq[st]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        inq[u]=0;
        for(int i=head[u];~i;i=edges[i].nex){
            int v=edges[i].v;
            if(dis[v]>dis[u]+1){
                dis[v]=dis[u]+1;
                if(inq[v]==0){
                    inq[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int f[maxn];
vector<pair<int,int> > v;
int main(){
    memset(head,-1,sizeof head);
    cnt=0;
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;++i){
        ds[i]=dt[i]=10000000000000;
    }
    for(int i=1;i<=k;++i){
        cin>>a[i];
    }
    for(int i=1;i<=m;++i){
        int u,v;
        cin>>u>>v;
        addedge(u,v);
        addedge(v,u);
    }
    spfa(1,ds);
    spfa(n,dt);
    for(int i=1;i<=k;++i){
        v.push_back({ds[a[i]]-dt[a[i]],a[i]});
    }
    sort(v.begin(),v.end());
    long long res=0,tmp=0;
    for(int i=0;i<v.size();++i){
        int u=v[i].second;
        if(i!=0){
            res=max(res,tmp+dt[u]+1);
        }
        tmp=max(tmp,ds[u]);
    }
    cout<<min(res,ds[n]);
    return 0;
}

以上是关于Codeforces Round #621 (Div. 1 + Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #621 (Div. 1 + Div. 2) 题解

Codeforces Round #621 (Div. 1 + Div. 2)D dij(思维)

Codeforces Round #621 (Div. 1 + Div. 2)A-C简单记录

Codeforces Round #621 (Div. 1 + Div. 2) D

Codeforces Round #621 (Div. 1 + Div. 2).D. Cow and Fields

Codeforces Round #621 (Div. 1 + Div. 2)B Cow and Friend