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

A. Cow and Haybales

思路:

在任何时候,最理想的做法是将最近的一堆草垛从桩1移到左侧。 因此,每天,我们都可以从左到右遍历一堆桩,并将我们看到的第一个草垛移近。 如果某个时候所有干草捆都堆放在第1堆中,我们可以早点停下来

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#include<iostream>
using namespace std;
inline ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
const int manx=1e5+5;
ll a[manx];
int main()
{
    ll kk=read();
    while(kk--)
    {
        ll n,m;
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++) cin>>a[i];
        ll kkk=0;
        for(int i=2;i<=n;i++){
            if(!a[i]) continue;
            if(m>=(i-1)){
                ll res=m/(i-1);
                if(a[i]<res) m-=a[i]*(i-1),kkk+=a[i];
                else m%=(i-1),kkk+=res;
            }
            else break;
        }
        cout<<a[1]+kkk<<endl;
    }

    return 0;
}
View Code

B. Cow and Friend

思路:

如果最喜欢的数字里包含x那么答案就为1

否则,设能跳的最远距离为max,如果max大于x的话那么答案就为2,如果小于x的话答案就为(x/max)向上取整

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
 using namespace std;
 typedef long long ll;
 const int maxn=1e5+10;
 int a[maxn];
 int main()
 {
     int yy;
     cin>>yy;
     while(yy--){
         int n,x;
         scanf("%d%d",&n,&x);
         int k=0,fla=0;
         for(int i=1;i<=n;i++){
             scanf("%d",&a[i]);
             if(a[i]<=x){
                 k=max(a[i],k);
             }
            if(a[i]>x){
                fla=1;
            }
         }
        if(fla&&k!=x){
            cout<<2<<endl;
            continue;
        } 
        if(!(x%k)) cout<<x/k<<endl;
        else cout<<(x/k+1)<<endl; 
     }
 }
View Code

 

C. Cow and Message

思路:

由于有等差数列这个限制,所以两个以上字母的组合是肯定没有两个字母组合更有,因此我们只要枚举26*26个字母的组合看看哪种组合的出现次数最多即可,注意两个相同数字的组合也有可能是最大的

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define maxn 100010
ll letter[maxn][30],vis[30][30],hz[30]={0},cnt[30]={0};
int main()
{
    memset(vis,0, sizeof(vis));
    memset(letter,0, sizeof(letter));
    string s;
    cin>>s;
    int n=s.length();
    for (int i = 0; i <n ; ++i) {
        if(i>0){
            for (int j = 0; j <26 ; ++j) {
                letter[i][j]=letter[i-1][j];
            }
        }
        letter[i][s[i]-'a']++;
        cnt[s[i]-'a']++;
    }
    for (int k = 0; k <n-1 ; ++k) {
        for (int i = 0; i <26 ; ++i) {
            hz[i]=letter[n-1][i]-letter[k][i];
            vis[s[k]-'a'][i]+=hz[i];
        }
    }
    ll kk=0;
    for (int l = 0; l <26 ; ++l) {
        for (int i = 0; i <26 ; ++i) {
            if(vis[l][i]>kk) kk=vis[l][i];
        }
    }
    for (int m = 0; m <26 ; ++m) {
        if(cnt[m]>kk) kk=cnt[m];
    }
    cout<<kk<<endl;
    return 0;
}
View Code

 D. Cow and Fields

思路:

由于加上一条边后,只会使最短路继续变短不会边长,所以假设未加边的最短路长度为len

我们先用BFS得到从1的i的最短路p[i] ,从n到i的最短路q[i]

那么加完边之后的最短路就应该为min(len,min(p[sq[t1,p[tq[s1)

我们继续将p[sq[tp[tq[s]等式变形成为 p[s] - q[s] <p[t] - q[t] 

因此我们只需要对p[s] - q[s] 排序,然后遍历一下k个特殊点:那么当前遍历到的t,那么t与之前所有的点直接的最短路都是min(p[s]+q[t]+1,len),把p[s]的最大值记录一下即可。

#include<iostream>
#include<algorithm> 
#include<cstring>
#include<queue>
#include<vector>
#define inf 0x3f3f3f3f
 using namespace std;
 const int maxn=2e5+10;
 int dis[2][maxn],a[maxn],vis[maxn];
 int n,m,k;
 vector<int> e[maxn];
 int cmp(int x,int y){return dis[0][x]-dis[1][x]<dis[0][y]-dis[1][y];}
 void dfs(int *dis,int x)
 {
     memset(vis,0,sizeof(vis));
     queue<int> q;
     dis[x]=0;
     vis[x]=1;
     q.push(x);
     while(!q.empty()){
         int now=q.front();
         q.pop();
         for(int i=0;i<e[now].size();i++){
             if(!vis[e[now][i]]){
                 vis[e[now][i]]=1;
                 q.push(e[now][i]);
                 dis[e[now][i]]=dis[now]+1;
             }
         }
     }
 }
 int main()
 {
     scanf("%d%d%d",&n,&m,&k);
     for(int i=0;i<k;i++) scanf("%d",&a[i]);
     for(int i=1;i<=m;i++){
         int u,v;
         scanf("%d%d",&u,&v);
         e[u].push_back(v);
         e[v].push_back(u);
     }
    dfs(dis[0],1);
    dfs(dis[1],n);
     sort(a,a+k,cmp);
    int ans=0,mx=-inf;
    for(int i=0;i<k;i++){
        ans=max(ans,mx+dis[1][a[i]]+1);
        mx=max(mx,dis[0][a[i]]);
    }
    cout<<min(dis[0][n],ans)<<endl;
 }
View Code

 

posted @ 2020-02-18 13:56  overrate_wsj  阅读(300)  评论(1编辑  收藏  举报