• 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;
    }
    
  • 相关阅读:
    Linux下软件安装方法即路径设置
    maven和jdk版本不匹配
    jobTracker 和taskTracker
    任务调度quartz
    springside3.1.8打包
    给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组
    二进制求和
    数组中找到目标值,并返回其索引
    加1问题
    给定字符串返回最后一个单词的长度
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12517263.html
Copyright © 2020-2023  润新知