牛客小白月赛6

B题:

链接:https://www.nowcoder.com/acm/contest/136/B
来源:牛客网
 

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    化而为鸟,其名为鹏。鹏之背,不知其几千里也。

                                        ——《庄子·逍遥游》

    HtBest的小鲲长大变成了大鹏,大鹏在天际翱翔,看到了一片绵延的山脉,每座山都有自己的高度,大鹏想穿过这片山脉。由于他只能紧贴地面飞行,他想知道他一共要翻越几次大山(上升->平飞->下降,算一次,其中平飞可以没有),初始时,大鹏在山脉的左端。

输入描述:

第一行一个正整数n,表示山脉被分为n段。
第二行有n个正整数ai两两之间用空格分开,ai表示山脉第i段的高度。

输出描述:

一行,包含一个正整数,表示大鹏需要翻越几次大山。

 

示例1

输入

复制

3
1 2 1 

输出

复制

1

说明

大鹏先上升一次,再下降一次,共翻越1次。

示例2

输入

复制

3
3 1 2

输出

复制

0

说明

大鹏先下降一次,再上升一次,共翻越0次。

示例3

输入

复制

3
1 2 3

输出

复制

0

说明

大鹏只需要上升一次,不需要下降,共翻越0次。

备注:

对于100%的测试数据:
1 ≤ n ≤ 1000000
1 ≤ ai ≤ 1000000000
数据量较大,注意使用更快的输入输出方式。

思路:

很简单的一道签到,暴力找出翻越的次数就行了,可以用一个bool值flag翻滚求

代码:

#include
using namespace std;
const int maxn = (int)1e6 + 10;
int a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    int ans = 0;
    for (int i = 0;i < n;i ++)
        scanf("%d",&a[i]);
    bool flag = 0;
    for (int i = 1;i < n;i ++)
    {
        if (flag && a[i] < a[i - 1])
        {
            flag = 0;
            ans ++;
        }
        if (a[i] > a[i - 1])
            flag = 1;
    }
    printf("%d\n",ans);
    return 0;
}

D题:

链接:https://www.nowcoder.com/acm/contest/136/C
来源:牛客网
 

桃花

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    桃花一簇开无主,可爱深红映浅红。

                                        ——《题百叶桃花》

    桃花长在桃树上,树的每个节点有一个桃花,调皮的HtBest想摘尽可能多的桃花。HtBest有一个魔法棒,摘到树上任意一条链上的所有桃花,由于HtBest法力有限,只能使用一次魔法棒,请求出Htbest最多可以摘到多少个桃花。

输入描述:

第一行有一个正整数n,表示桃树的节点个数。
接下来n-1行,第i行两个正整数ai,bi ,表示桃树上的节点ai,bi之间有一条边。

输出描述:

第一行一个整数,表示HtBest使用一次魔法棒最多可以摘到多少桃花。

 

示例1

输入

复制

3
1 2
2 3

输出

复制

3

示例2

输入

复制

3
1 2
1 3

输出

复制

3

示例3

输入

复制

4
1 2
2 3
3 4

输出

复制

4

备注:

对于100%的测试数据:
1 ≤ n ≤ 1000000
数据量较大,注意使用更快的输入输出方式。

思路:

题意很简单,就是求从一端尾部节点到别的端点经过的最多的节点数量,假设每个父节点与其子节点的距离都为1,那么我们求出树的直径再+1不就行了,牛客的评测机真的有毒,提交第一遍TLE,第二遍相同的代码就过了(900+ms),不管我就这样写了

代码;

#include
using namespace std;
const int maxn = (int)1e6 + 10;
vector > G[maxn];
int dis[maxn],ans;
bool vis[maxn];
int bfs(int x)
{
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue que;
    que.push(x);
    vis[x] = 1;
    int point = 0;
    while (!que.empty())
    {
        int p = que.front();
        que.pop();
        if (dis[p] > ans)
        {
            ans = dis[p];
            point = p;
        }  
        pair t;
        for (int i = 0;i < G[p].size();i ++)
        {
            t = G[p][i];
            if (vis[t.first] == 0)
            {
                vis[t.first] = 1;
                dis[t.first] = dis[p] + t.second;
                que.push(t.first);
            }
        }
     }
     return point;
}
int main()
{
    int n;
    scanf("%d",&n);
    int u,v;
    for (int i = 0;i < n - 1;i ++)
    {
        scanf("%d %d",&u,&v);
        G[u].push_back(make_pair(v,1));
        G[v].push_back(make_pair(u,1)); 
    }
    ans = 0;
    int p = bfs(1);
    ans = 0;
    bfs(p);
    printf("%d\n",ans + 1);
    return 0;
}

D题:

链接:https://www.nowcoder.com/acm/contest/136/D
来源:牛客网
 

符串丝带

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld

题目描述

    WHZ送给了HtBest一个“字符串丝带”,这条丝带由n个小写字母按照一定的顺序排列组成,HtBest收到新礼物后有许多问题,类似“第i个位置的字母在前i个位置中出现了几次?”,HtBest很希望知道答案,于是求助你帮忙解答。

 

输入描述:

第一行有2个正整数n,m,分别表示丝带长度和问题个数。
第二行,有n个小写字母,第i个表示丝带第i位的小写字母。
接下来有m行,每行一个正整数 ,表示HtBest的一个问题。

输出描述:

共m行,对于每个问题,给出答案。

 

示例1

输入

复制

3 3
abc
1
2
3

输出

复制

1
1
1

示例2

输入

复制

4 4
abba
1
2
3
4

输出

复制

1
1
2
2

示例3

输入

复制

7 7
yyuahhy
7
6
5
4
3
2
1

输出

复制

3
2
1
1
1
2
1

备注:

对于100%的测试数据:
1 ≤ n ≤ 1000000
数据量较大,注意使用更快的输入输出方式。

思路:

这题也是一道很简单的签到题,只需要预处理另开一个ch数组存前面每个字母的出现次数,一个num数组存当前位置该字母出现的次数即可

代码:

#include
using namespace std;
const int maxn = (int)1e6 + 10;
char s[maxn];
int num[maxn];
int ch[30];
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    scanf("%s",s);
    memset(ch,0,sizeof(ch));
    for(int i = 0;i < n;i ++)
    {
        ch[s[i] - 'a'] ++;
        num[i] = ch[s[i] - 'a'];
    }
    int p;
    for (int i = 0;i < m;i ++)
    {
        scanf("%d",&p);
        printf("%d\n",num[p - 1]);
    }
    return 0;
}

H题:

链接:https://www.nowcoder.com/acm/contest/136/H
来源:牛客网
 

挖沟

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述


    胡队长带领HA实验的战士们玩真人CS,真人CS的地图由一些据点组成,现在胡队长已经占领了n个据点,为了方便,将他们编号为1-n,为了隐蔽,胡队长命令战士们在每个据点出挖一个坑,让战士们躲在坑里。由于需要在任意两个点之间传递信息,两个坑之间必须挖出至少一条通路,而挖沟是一件很麻烦的差事,所以胡队长希望挖出数量尽可能少的沟,使得任意两个据点之间有至少一条通路,顺便,尽可能的∑d[i][j]使最小(其中d[i][j]为据点i到j的距离)。

输入描述:

第一行有2个正整数n,m,m表示可供挖的沟数。
接下来m行,每行3个数a,b,v,每行描述一条可供挖的沟,该沟可以使a与b连通,长度为v。

输出描述:

输出一行,一个正整数,表示要使得任意两个据点之间有一条通路,至少需要挖长的沟。(数据保证有解)

 

示例1

输入

复制

2 2
1 2 1
1 2 3

输出

复制

1

示例2

输入

复制

3 3
1 2 3
2 3 4
1 3 5

输出

复制

7

备注:

对于100%的测试数据:
1 ≤ n ≤ 100000
1 ≤ m ≤ 500000
1 ≤ v ≤ 10000

思路:

一道很明显的最小生成树,kruscal过的

代码:

#include
using namespace std;
const int maxn = (int)5e5 + 10;
const int MAXN = (int)1e5 + 10;
int f[MAXN];
struct node
{
	int u,v,cost;
}a[maxn];
bool cmp(node x,node y)
{
	return x.cost < y.cost;
}
int find(int x)
{
	if (x != f[x])
		f[x] = find(f[x]);
	return f[x];
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for (int i = 1;i <= n;i ++)
		f[i] = i;
	for (int i = 0;i < m;i ++)
		scanf("%d %d %d",&a[i].u,&a[i].v,&a[i].cost);
	sort(a,a + m,cmp);
	int ans = 0,cnt = 1;
	for (int i = 0;i < m;i ++)
	{
		if (cnt == n)
			break;
		int fx = find(a[i].u),fy = find(a[i].v);
		if (fx != fy)
		{
			cnt ++;
			ans += a[i].cost;
			f[fx] = fy;
		}
	}
	printf("%d\n",ans);
	return 0;
} 

 

你可能感兴趣的:(牛客网)