ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-04-14 15:01:16  阅读:194  来源: 互联网

标签:子串 ... 621 int Codeforces maxx Div now dis


A. Cow and Haybales

题意:有n堆干草,每次可以挑相邻的两个数,一个加一一个减1,求这样搬d次后第一堆干草最多有多少。

解:一开始读假题了,以为要求d次操作后高度为1的干草堆最多有多少。。。直接从左到右把能搬的草搬完就行。

B. Cow and Friend

题意:起点为0,终点为x。给出n个数,每次可以选一个数在二维平面上跳相应长的距离,求最少几次能跳完。

解:令能跳的最大距离为m,m>x时,如果有能直接到终点的距离答案为1,否则两下能跳过去;m=x答案为1;m<x时,按最大距离跳,最后走个三角形,即答案为(d-1)/x+1,减一是为了兼容x为m倍数的情况。

C. Cow and Message

题意:给出一个字符串,挑出它所有下标为等差数列的子串,求出现最多的子串出现了几次。

解:如果出现最多的子串长为3,那么长为2的子串也出现了这么多次。所以最终答案只能由长为1或2的子串带来,暴力枚举计数即可。

D. Cow and Fields

题意:给出一张图和其中顶点的一个子集,可以在子集中选两个点加一条边,求加完这条边后起点1到终点n最短路的最大值。

解:首先加了这条边后最短路不可能边长,那么考虑怎么加能使最短路变短得更少。首先如果原来有这条边,那选它一定是最好的;由此引出了一个错误做法:整张图bfs一遍分层,挑层数相差最小的加边。这个做法竟然跑过了31个点。

但这张图如果选起点和终点就GG了。

 

所以老实考虑计算式子:选点x和y,新的最短路长度为min(dis[0...x]+1+dis[y...n],dis[0...y]+1+dis[x...n],原最短路长度)。O(n2)显然不行,考虑移项:

dis[0...x]+dis[y...n]<dis[0...y]+dis[x...n]

dis[0...x]-dis[x...n]<dis[0...y]-dis[y...n]

现在一边只有一个未知数,可以考虑按这个差值排序,从而保证答案一定是从前往后选两个点。最终答案要dis[0...x]+dis[y...n]+1,那遍历一遍挑最大的就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define inf 0x7fffffff
int n,m,k;
int a[maxx]={0};
vector<int> e[maxx];
int vis[maxx]={0};
int dis[maxx][2];
void dijk(int start,int num){
    for(int i=1;i<=n;i++)
        dis[i][num]=inf,vis[i]=0;
    priority_queue<pair<int,int> > q;
    dis[start][num]=0;
    q.push(make_pair(0,start));
    while(!q.empty()){
        int now=q.top().second;
        q.pop();
        if(vis[now])
            continue;
        vis[now]=1;
        for(auto to:e[now]){
            int f=dis[now][num]+1;
            if(f<dis[to][num]){
                dis[to][num]=f;
                q.push(make_pair(-dis[to][num],to));
            }
        }
    }
}
signed main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dijk(1,0);
    dijk(n,1);
    int ans=0;
    sort(a+1,a+k+1,[](int x,int y){
        return dis[x][0]-dis[x][1]<dis[y][0]-dis[y][1];
    });
    int maxn=-inf;
    for(int i=1;i<=k;i++){
        ans=max(ans,maxn+dis[a[i]][1]);
        maxn=max(maxn,dis[a[i]][0]);
    }
    printf("%d\n",min(ans+1,dis[n][0]));
    return 0;
}
View Code

 

标签:子串,...,621,int,Codeforces,maxx,Div,now,dis
来源: https://www.cnblogs.com/capterlliar/p/16144556.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有