牛客小白月赛-说谎的机器


title: 牛客小白月赛-说谎的机器
tags: 前缀和
abbrlink: d2c37c9a
date: 2022-06-19 19:25:26

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

题目描述

牛牛在和它的机器玩猜数字,可是机器好像坏了……
具体来说,机器首先会随机生成一个 1…n的数字 k,紧接着机器会给牛牛 m 条指令,指令的格式有如下三种:
1、op x y;这里,op=1 代表有 x≤k≤y
2、op x;这里, op=2 代表有 x≤k≤n
3、op x;这里, op=3 代表有 1≤k≤x
牛牛知道这台机器已经学会了说谎,所以它所描述的指令可能都是错误的,现在牛牛想知道机器错误的程度以便来制定修理它的方案。

所以牛牛想请你告诉它,当 k 取 1…n 这个范围内的值时,机器最多有多少条指令是错误的,而 k 又有多少种取值方式使得机器的错误指令数最多。

输入描述:

第一行两个整数代表 n,mn,mn,m 

接下来 mmm 行每行一条指令,指令格式见题面。
保证:
1≤n≤106;    1≤m≤2×105; 1≤op≤3;  

输出描述:

输出共一行两个整数,分别代表机器最多的错误指令数,以及有多少种 k 的取值会使得机器的错误指令数最多。

示例1

输入

[复制](javascript:void(0)😉

9 5
1 3 6
2 7
1 2 3
3 2
1 5 8

输出

[复制](javascript:void(0)😉

4 3

说明

最多的错误指令数为 4。
使得错误指令数最多的取值有 3 种,分别是:
  取值为 1,此时第 1、2、3、5 条指令是错误的。
  取值为 4,此时第 2、3、4、5 条指令是错误的。
  取值为 9,此时第 1、3、4、5 条指令是错误的。

笔者解析

本题是小白月赛中的第三题,使用一维差分数组来计算相关所需数据。

若要是的计算范围为错误的,则要避开正确答案

p1 则错误的情况为1<= k < x && y < k <=n
p2 则表示1<=k<x &&n<k,但是题目已经告知k在1~n范围内
p3 则表示x<k<=n

笔者代码

java版本

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static int N = 1000010;

	public static void main(String[] args) throws IOException {
		// 使用差分来进行处理本题
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String[] str = reader.readLine().split(" ");
		int n = Integer.parseInt(str[0]);
		int m = Integer.parseInt(str[1]);
		
		//差分数组
		int[] a = new int[N];
		
		//所需的书据
		int x,y;
		
		//进行差分运算
		while(m-->0){
			str = reader.readLine().split(" ");
			if(str[0].equals("1")){
				x = Integer.parseInt(str[1]);
				y = Integer.parseInt(str[2]);
				//则错误的情况为1<= k < x && y < k <=n
				a[1]++;a[x]--;
				a[y+1]++;a[n+1]--;
			}else if(str[0].equals("2")){
				x = Integer.parseInt(str[1]);
				//则表示1<=k<x &&n<k,但是题目已经告知k在1~n范围内
				a[1]++;a[x]--;
			}else {
				x = Integer.parseInt(str[1]);
				//则表示x<k<=n
				a[x+1]++;a[n+1]--;
			}
		}
		
		//使用差分数组计算前缀和
		for(int i = 1;i<=n;i++){
			a[i] += a[i-1];
		}
		
		int max = -1,all = 0;
		for(int i = 1;i<=n;i++){
			max=Math.max(max, a[i]);
		}
		for(int i = 1;i<=n;i++){
			if(a[i]==max){all++;}
		}
		
		System.out.println(max+" "+all);
	}

}

C++版本

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10;
int a[N];
int n,m;
int main()
{
    scanf("%d%d", &n, &m);
    while (m -- )
    {
        int op,x,y;
        cin>>op>>x;
        if(op==1)
        {
            cin>>y;
            a[1]++,a[x]--;
            a[y+1]++,a[n+1]--;
        }
        else if(op==2)
        {
            a[1]++,a[x]--;
        }
        else 
        {
            a[x+1]++,a[n+1]--;
        }
    }
    for(int i=1;i<=n;i++) a[i]+=a[i-1];
    int maxn=0,res=0;
    for(int i=1;i<=n;i++)
    {
        maxn=max(maxn,a[i]);
    }
    for(int i=1;i<=n;i++) if(a[i]==maxn) res++;
    cout<<maxn<<' '<<res<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值