牛客小白月赛30题解

比赛传送门

没有参加正式赛,创了场重现赛来玩玩,AC8题

做最后俩题只剩15分钟,感觉没时间了就没写qwq

补题的时候发现并没有比前面的题目难多少呜呜呜

感觉小白赛的题目和以往相比变得简单了很多

考查了简单的数据结构以及它的应用,重点应该还是对思维的考察


A 黑白边

题目描述:

n个点,m条边,每条边分为黑边和白边,现在需要挑一些边出来,使得n个点可以两两联通。

由于牛牛特别讨厌白边,所以在挑中的边中,让白边最少,输出白边的条数,如果不能两两联通,输出−1.

输入描述:

第一行两个整数 n , m n,m n,m ( 1 ≤ n , m ≤ 2 e 5 ) (1≤n,m≤2e5) (1n,m2e5)

接下来 m 行, 每行三个整数 x,y,z 代表xy之间有一条边。z的值为0或1,0 代表黑边,1代表白边

输出描述:

一行一个整数, 表示最少的白边数量。如果不能满足题目条件,输出 -1

样例输入:
4  4
1 2 0
2 3 0
3 4 1
1 4 0
样例输出:
0
思路:

明显的并查集

先将黑边都连上,再对白边逐一判断

如果某条白边连接的俩个点已经连通,则不连,反之则连上

最后再判断连通分量是否为1

代码:
#include<bits/stdc++.h>
using namespace std;

const int MAXN = 2e5+5;
struct node{
   int u,v;}arr[MAXN];
int fa[MAXN];
int N,M,cnt,ans,ttt;
void merge(int x,int y);
int find(int x);

int main()
{
   
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++) fa[i]=i;
    for(int i=1;i<=M;i++){
   
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(z==0) merge(x,y);
        else arr[++cnt]=node{
   x,y};
    }
    for(int i=1;i<=cnt;i++){
   
        if(find(arr[i].u)!=find(arr[i].v)){
   
            merge(arr[i].u,arr[i].v);
            ans++;
        }
    }
    for(int i=1;i<=N;i++){
   
        if(i==fa[i])
            ttt++;
    }
    if(ttt==1) printf("%d",ans);
    else printf("-1");
    return 0;
}

void merge(int x,int y)
{
   
    fa[find(x)]=find(y);
}


int find(int x)
{
   
    if(x==fa[x]) return x;
    else return fa[x]=find(fa[x]);
}


B 最好的宝石

题目描述:

牛牛有n个宝石,第i个宝石的价值是 w [ i ] w[i] w[i].

有m个操作,操作分为两种类型

  • Change x y 把第x个宝石的价值改成 y

  • Ask l r 询问区间[l,r]内宝石的最大价值,和最大价值的宝石有多少个。

输入描述:

第一行两个整数 n , m (1 ≤ n,m ≤ 2e5)

第二行有n个整数 w[i] (0 ≤ w[i] ≤ 1e9)

接下来m行,每行代表一个操作。具体见题目描述。

输出描述:

每次询问输出一行,每行两个整数 val cnt

val代表所有宝石中的最大价值,cnt代表价值最大的宝石有多少个。

样例输入:
5 3
2 4 3 6 8
Ask 1 5
Change 2 10
Ask 1 3
样例输出:
8 1
10 1
思路:

线段树上支持单点修改,查询区间最值,区间最值个数的操作

单点修改和区间最值都是老操作了,这个最值个数倒是少见qwq

那就在原线段树的基础上,加上一个区间最值的个数的变量

本题没有下推,而在上推的过程中

若左儿子的区间最值等于右儿子,那父亲节点的最值个数就是左右俩个最值的和

若左儿子的最值大于右儿子,父亲节点的最值个数等于左儿子,右儿子同理

那就做完了。

代码:
#include<bits/stdc++.h>
using namespace std;

const int MAXN = 2e5+5;
int N,M;
struct node{
   
    int l,r;
    int cnt,val;
    node(){
   cnt=-1;val=-1;}
}T[MAXN<<2];
int arr[MAXN];
int x,y;
string op;
void build(int pos,int l,int r);
node query(int pos,int x,int y);
void update(int pos,int x,int k);
void upush(int pos);

int main()
{
   
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++) scanf("%d",&arr[i]);
    build(1
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值