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

QAQ

A. Cow and Haybales

题意:

n个盒子,第i个盒子初始有ai个物品,每一天你可以把某个盒子的一个物品移动到相邻盒子里,求d天之后第一个盒子最多有多少个物品

思路:

简单题,直接模拟即可,详细见代码。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5e4+5;
int num[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,d;
        scanf("%d %d",&n,&d);
        for(int i = 1;i<=n;++i)
            scanf("%d",&num[i]);
        for(int i  =2;i<=n;++i)
        {
            int cost = i-1;
            int tmp  = d/cost;
            tmp = min(tmp,num[i]);
            num[1]+=tmp;
            num[i]-=tmp;
            d-=tmp*cost;
            if(num[i]>0)
                break;
        }
        cout << num[1]<< "\n";
    }
    return 0;
}

B. Cow and Friend

题意:

给你一个位于x轴上的点k,以及m个你-次能走的距离,求从原点出发,你最少走几次能到达k点,输出次数。

思路:

首先,如果可以一步走到的话只需要走一步,假如一步走不到的话,设他所能走的最大步数是max,我们首先水平向右走到距离小于等于2*max,然后最后的一点距离一定可以用两步max斜着走来实现。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
LL num[maxn];
set<LL> s;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        s.clear();
      LL n,x;
      cin >> n >>x;
      LL ma = 0;
     LL ans = 0;
      for(int i =1;i<=n;++i )
      {
          cin >> num[i];
          s.insert(num[i]);
          ma =max(ma,num[i]);
      }
     // LL ans = 0;
    // cout << "ma  = " << ma << "\n";
      if(s.find(x)!=s.end())
      {
          ans = 1;
      }
      else
      {
          if(x<=2*ma)
                ans = 2;
          else
          {
              ans = x/ma;
              if(x%ma)
              ++ans;
          }
      }
      cout << ans << "\n";
    }
    return 0;
}

C. Cow and Message

题意:

给你一个字符串,求某个子序列出现的最大次数,子序列中的相邻元素在原串中的距离一定相同,输出出现的最大次数。

思路:

可以知道的是,最优解解只能从长度为1的子序列以及长度为2的子序列中选取,基于这个条件,我们就很容易得出这个题的思路。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
LL cnt[30],c2[30],num[30][30];
int main()
{
    string s;
    cin >> s;
    int len = s.size();
    LL ans = 0;
    for(int i = 0;i<len;++i)
        ++cnt[s[i]-'a'];
    for(int i  = 0;i<26;++i)
        ans = max(ans,cnt[i]);
    for(int i = 0;i<len;++i)
    {
       // c2[s[i]-'a']++;
        cnt[s[i]-'a']--;
        for(int j = 0;j<26;++j)
        {
            num[s[i]-'a'][j]+=cnt[j];
        }

    }
    for(int i = 0;i<26;++i)
    {
        for(int j = 0;j<26;++j)
            ans = max(ans,num[i][j]);
    }
    cout << ans << "\n";
    return 0;
}

D. Cow and Fields

题意:

给定一个有n个顶点的树,其中有k个特殊顶点,,你必须且只能在选择两个特殊点连接一条边,使得从1-n的最短路最大,输出最短路的长度。

思路:

对于一个特殊点p来说,我们定义他到1的距离是f(p),他到n的距离是g(p),现在我们假设选择建边的两个点是下xy,那么1-n的路径有两种可能。

第一种是1-xx-yy-n,路径长度为f(x)+1+g(y);

第二种是1-yy-xx-n,路径长度为f(y)+1+g(x);

为了方便计算,我们把第一种认为是最优的,则应该有 f(x)+1+g(y)>=f(y)+1+g(x),则有f(x)-g(x)>=f(y)-g(y)

如果我们依照上面的规则排个序,则最优路径的选择一定是第二种情况(因为在两条路径都存在时要取较小的那一条)。这是,对于路径长度f(x)+1+g(y),我们只需要找到最大的f(x),以及最大的g(y)即可。

要注意的是,在上面的讨论中我么们只是考虑了它一定走这条新建边的情况,所以最后求出的答案还要跟原先的最短路取个最小值。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
int n,m,k;
vector<int>G[maxn];
int dis[2][maxn],a[maxn],vis[maxn];
void bfs(int x,int st)
{
    memset(vis,0,sizeof(vis));
    for(int i = 1;i<=n;++i)
        dis[x][i] = 1e9;
    queue<int>Q;
    dis[x][st] = 0;
    vis[st] = 1;
    Q.push(st);
    while(!Q.empty())
    {
        int now = Q.front();
        Q.pop();
        for(int i = 0;i<G[now].size();++i)
        {
            int nxt = G[now][i];
            if(vis[nxt]) continue;
            dis[x][nxt] = dis[x][now]+1;
            Q.push(nxt);
            vis[nxt] = 1;
        }
    }
}
int main()
{
    cin >> n >> m >> k;
    for(int i = 0;i<k;++i)
        cin >> a[i];
    for(int i =0;i<m;++i)
    {
        int x,y;
        cin >> x>> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    bfs(0,1);
    bfs(1,n);
    int ans = 0;
    vector<pair<int,int> >V;
    for(int i = 0;i<k;++i)
    {
        V.push_back(make_pair(dis[0][a[i]]-dis[1][a[i]],a[i]));
    }
    sort(V.begin(),V.end());
    int tmp = 0;
    for(int i = 0;i<V.size();++i)
    {
        if(i!=0)
        {
            ans = max(ans,tmp+dis[1][V[i].second]+1);
        }
        tmp = max(tmp,dis[0][V[i].second]);
    }
    cout << min(ans,dis[0][n]) << "\n";
    return 0;
}
posted @ 2020-03-10 18:45  浅花迷人  阅读(183)  评论(0编辑  收藏  举报