模拟算法(acw)

模拟算法题:不是用经典算法解出来的题目都可以称为模拟题。

目录

01 - 错误票据

02 - 回文日期

03 - 移动距离

04 - 日期问题

知识点 - 结构体的使用

05 - 航班时间

知识点 - sscanf、c_str、getline

06 - 外卖店优先级


题目来源于蓝桥杯比赛真题


01 - 错误票据

题目链接:acw - 1204.错误票据

题目详情:

某涉密单位下发了某种票据,并要在年终全部收回。

每张票据有唯一的ID号。

全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。

因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。

你的任务是通过编程,找出断号的ID和重号的ID。

假设断号不可能发生在最大和最小号。

输入格式

第一行包含整数 N,表示后面共有 N 行数据。

接下来 N 行,每行包含空格分开的若干个(不大于100个)正整数(不大于100000),每个整数代表一个ID号。

输出格式

要求程序输出1行,含两个整数 m,n用空格分隔。

其中,m表示断号ID,n表示重号ID。

数据范围

1≤N≤100

输入样例

2
5 6 8 11 9 
10 12 9

输出样例:

7 9

分析

方法1

开一个bool数组来记录每个数是否被用过

方法2

排序

方法1 - 代码

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100010;	//每个正整数不大于100000 
bool st[N] = {0};
int a[N];
int m,n;

int main()
{
	cin>>n;	//n行

	int flag = 0;	//数组下标 
	while(n --)
	{ 
		int i;
		while( cin>>i ){
		    //必须要在判断的前面
			a[flag ++ ] = i;

			//遇到换行符'\n'终止 
			char c = cin.get();
			if(c == '\n') break;
				 
		}
		
	}
	
	
	//找重号 
	for(int i = 0; i < flag; i ++)
	{
	    //如果原先已经出现过,表示是重号
		if( st[a[i]] ) 
			n = a[i];
		//将出现过的数的状态设置为 true
		st[a[i]] = true;
	}

	//找断号
	int start = 0;	            //票号从一个随机的数开始 
	while(!st[start]) start ++; //找票据的最小值
	for(int i = start; i < start + flag; i ++){
		if( !st[i] ){
			m = i;
			break;
		}
	}
	
	cout<<m<<" "<<n<<endl;
	return 0;
}

方法2 - 代码

#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 10010;	//每个正整数不大于100000 
bool st[N] = {0};
int a[N];
int m,n;
int flag;

//方法2 -- 排序
int main()
{
	int cnt;
	cin>>cnt;
	string line;	
	//用getline读,但是回车也会被读进去
	getline(cin,line);	//忽略掉第一行的回车 
	while(cnt--)
	{
		getline(cin,line);
		stringstream ssin(line);
		
		//初始完后可以从line中一个个读取字符 
		//像cin一样用ssin,读取字符的地方不一样 
		while(ssin >> a[flag]) flag++; 
	}
	
	sort(a,a + flag);
	
	//断号不会是最大或最小值 
	for(int i = 1; i < flag; i ++)
	{
		if(a[i] == a[i-1]) 
			n = a[i];
		else if(a[i] > a[i-1] + 1) 
			m = a[i] - 1;
	}
	
	cout<<m<<" "<<n;
	
	return 0;
} 

02 - 回文日期

枚举 + 模拟 组合版

题目链接:acw - 466.回文日期

 题目详情

在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用 88 位数字表示一个日期,其中,前 4 位代表年份,接下来 2 位代表月份,最后 2 位代表日期。

显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的 8 位数字是回文的。

现在,牛牛想知道:在他指定的两个日期之间(包含这两个日期本身),有多少个真实存在的日期是回文的。

一个 8 位数字是回文的,当且仅当对于所有的 i(1≤i≤8) 从左向右数的第 i 个数字和第 9−i 个数字(即从右向左数的第 ii 个数字)是相同的。

例如:

  • 对于 2016 年 11 月 19 日,用 8 位数字 20161119 表示,它不是回文的。
  • 对于 2010 年 11 月 2 日,用 8 位数字 20100102 表示,它是回文的。
  • 对于 2010 年 10 月 2 日,用 8 位数字 20101002 表示,它不是回文的。

输入格式

输入包括两行,每行包括一个 8 位数字。

第一行表示牛牛指定的起始日期 date1,第二行表示牛牛指定的终止日期 date2。保证 date1 和 date2 都是真实存在的日期,且年份部分一定为 4 位数字,且首位数字不为 0。

保证 date1 一定不晚于 date2。

输出格式

输出共一行,包含一个整数,表示在 date1 和 date2 之间,有多少个日期是回文的。

输入样例:

20110101
20111231

输出样例:

1

分析 

代码

#include<iostream>
#include<algorithm>

using namespace std;

int days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

//判断日期是否合法
bool check_valid(int date)
{
	//获取回文数的年月日 
	int year = 	date / 10000;
	int month = (date % 10000) / 100;
	int day = date % 100;
	
	//判断月份是否合法
	if(month == 0 || month > 12) return false;
	//判断天数是否合法
	if(day == 0 || day > days[month] && month != 2) return false;
	//特判一下平年和闰年
	if(month == 2){
		int leap = year%4==0 && year%100!=0 || year%400 == 0;
		if(day > 28 + leap) return false; 
	} 

	return true;	
} 

int main()
{
	int date1,date2;
	cin>>date1>>date2;
	
	int res = 0;
	//枚举回文数 
	for(int i = date1/10000 ;i < 10000;i ++)
	{
		int date = i,x = i;
		while(x != 0){
			date = date*10 + x%10;
			x /= 10;
		}
	
		//判断是否在范围内 判断日期是否合法 
		if( date <= date2 && date >= date1 && check_valid(date) )
			res++;
	}
	
	cout<<res;
	return 0;	
}

03 - 移动距离

题目传送门 -- 移动距离

知识点 - 向上取整、向下取整

知识传送门 -- C++向上取整、向下取整

头文件

#include<math.h> 
或者 
#include<cmath> 

函数

函数名称函数说明
floor()不大于自变量的最大整数
ceil()不小于自变量的最大整数
round()四舍五入到最邻近的整数
fix()朝零方向取整

分析:

两种经典距离:

曼哈顿距离:
| x1 - x2 | + | y1 - y2 |
 

欧几里德距离:
√((x1 - x2)^2 + (y1 - y2)^2)
 

 

本题求的是曼哈顿距离

1)计算竖着走的步数

2)计算横着走的步数

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
​
using namespace std;
​
int w,m,n;
​
int main()
{
    scanf("%d%d%d",&w,&m,&n);
    
    int res = 0; 
    
    //mx,nx为m、n的行数,竖着走的步数即为他们相减的绝对值 
    int mx = ceil(m*1.0 / w);
    int nx = ceil(n*1.0 / w);
    
    //计算竖着走的步数
    res += fabs(nx - mx);
    
//测试 
//  cout<<"竖着:"<<res<<" ";
//  cout<<"mx:"<<mx<<" "<<"nx:"<<nx<<endl; 
​
    //计算横着要走的步数
    //my,ny为m、n的列数,相减即为横着要走的步数 
    int my = 0, ny = 0;
    if(mx % 2 != 0)         //当m在顺序行 
    {
        my = m % w;
        if(my == 0) my = w;
    }
    else if(mx % 2 == 0)    //当m在逆序行 
    {
        
        if(m%w == 0) my = 1;
        else my = (w - m%w + 1);
    }
    if(nx % 2 != 0)         //当n在顺序行 
    {
        ny = n % w;
        if(ny == 0) ny = w;
    }
    else if(nx % 2 == 0)    //当n在逆序行 
    {
        if(n%w == 0) ny = 1;
        else ny = (w - n%w + 1);
        
    }
//  //测试 
//  cout<<"横着:"<<fabs(ny - my)<<" ";
//  cout<<"my:"<<my<<" "<<"ny:"<<ny<<endl; 
​
    res += fabs(ny - my);
    
    cout<<res;
    return 0;
} 

上述方法用来求行号和列号有些许麻烦,我们不妨将每个楼号都减一,这样处理起来会简便许多,少了些特判

代码:

//2022.6.6 
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
​
int main()
{
    int w,m,n;
    cin>>w>>m>>n;
    m --, n --;
    
    int mx,my,nx,ny;
    mx = m/w, nx = n/w;
    my = m%w, ny = n%w;
    if(mx % 2 != 0) 
        my = w - 1 - my;
    if(nx % 2 != 0) 
        ny = w - 1 - ny;
    
    cout<<abs(mx - nx) + abs(my - ny)<<endl;
    
    return 0;
} 
​


04 - 日期问题

题目传送门 -- 日期问题

题意:

输入A,B,C三个两位的数字,代表的意义可能是年/月/日或月/日/年或日/月/年,其中年是年份的尾数,找出可能代表的合法日期,输出在1960年1月1日至2059年12月31日之间的日期

分析:

  1. 枚举所有日期:1960.1.1 ~ 2059.12.31

    19600101 ~ 20591231

  2. 判断是否为合法日期

  3. 判断是否是给定的表示


代码:

#include<cstdio>
#include<iostream>
​
using namespace std;
​
int days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
​
bool check_valid(int year,int month,int day)
{
    //判断月份是否合法
    if(month == 0 || month >12) return false;
    //判断一下天数是否合法
    if(day == 0 || month!=2 && day>days[month]) return false;
    //特判一下平年和闰年
    if(month == 2)
    {
        int leap = (year % 4 ==0 && year % 100 !=0 || year % 400 ==0);
        if(day > 28 + leap) return false; 
    } 
    
    return true;
}
​
int main()
{
    int a,b,c;
    scanf("%d/%d/%d",&a,&b,&c);
    for(int date = 19600101; date < 20591231; date ++)
    {
        int year = date / 10000;
        int month = date % 10000 / 100;
        int day = date % 100;
        //判断日期是否合法  
        if(check_valid(year,month,day))
        {
            //判断是否是给定的日期  
            //三种情况 
            if(year % 100 == a && month == b && day == c ||         //年/月/日
               year % 100 == c && month == a && day == b ||         //月/日/年
               year % 100 == c && month == b && day == a)           //日/月/年
            {
                printf("%d-%02d-%02d\n",year,month,day);
            }
                
        }
    }
    
    return 0;
}


知识点 - 结构体的使用

类型声明

struct stu
{
    char name[10];
    short age;
    char tele[20];
    char sex[5];
}s1,s2,s3;
int main()
{
    struct stu s4;
}   

struct 结构体关键字 stu 结构体标签 struct stu 结构体类型 s1,s2,s3 是三个全局的结构体变量 s4 是一个局部变量

用typedef将结构体改名为STU

typedef strustuct 
{
    char name[10];
    short age;
    char tele[20];
    char sex[5];
}STU;   
int main()
{
    STU s5;
}

注意: STU是类型,stu、STU可以同名 s1,s2,s3,s4,s5都是变量

//结构体变量的定义和初始化
struct Point
{
    char name[10]
    int x;
    int y;
}p1;                //声明类型的同时定义变量p1
struct Point p2;    //定义一个新变量p2
p2={"张三",100,90};
​
//结构体传参:
typedef struct stu
{
    char name[10];
    short age;
    char tele[20];
    char sex[5];
}STU;
​
void print1(STU ps)
{
    printf("name:%s\n", ps.name);
    printf("name:%d\n", ps.age);
    printf("tele:%s\n", ps.sex);
    printf("sex :%s\n", ps.sex);
}
void print2(STU* ps)
{
    printf("name:%s\n", ps->name);
    printf("name:%d\n", ps->age);
    printf("tele:%s\n", ps->tele);
    printf("sex :%s\n", ps->sex);
}
int main()
{
    STU s = { "张三",18,"1111","男" };
    //打印结构体数据
    print1(s);
    print2(&s);
}

  • print1和print2哪种打印的方式好一些?

    答案:首选print2

    原因:函数传参的时候,参数是需要压栈的,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

结论:结构体传参时,要传结构体的地址。


05 - 航班时间

题目传送门 -- 航班时间

题目详情:

小 h 前往美国参加了蓝桥杯国际赛。

小 hh 的女朋友发现小 h 上午十点出发,上午十二点到达美国,于是感叹到“现在飞机飞得真快,两小时就能到美国了”。

小 h 对超音速飞行感到十分恐惧。

仔细观察后发现飞机的起降时间都是当地时间。

由于北京和美国东部有 12 小时时差,故飞机总共需要 14 小时的飞行时间。

不久后小 h 的女朋友去中东交换。

小 h 并不知道中东与北京的时差。

但是小 h 得到了女朋友来回航班的起降时间。

小 h 想知道女朋友的航班飞行时间是多少。

对于一个可能跨时区的航班,给定来回程的起降时间。

假设飞机来回飞行时间相同,求飞机的飞行时间。

输入格式

一个输入包含多组数据。

输入第一行为一个正整数 T,表示输入数据组数。

每组数据包含两行,第一行为去程的起降时间,第二行为回程的起降时间。

起降时间的格式如下:

  1. h1:m1:s1 h2:m2:s2

  2. h1:m1:s1 h3:m3:s3 (+1)

  3. h1:m1:s1 h4:m4:s4 (+2)

第一种格式表示该航班在当地时间h1时m1分s1秒起飞,在当地时间当日h2时m2分s2秒降落。

第二种格式表示该航班在当地时间h1时m1分s1秒起飞,在当地时间次日h2时m2分s2秒降落。

第三种格式表示该航班在当地时间h1时m1分s1秒起飞,在当地时间第三日h2时m2分s2秒降落。

输出格式

对于每一组数据输出一行一个时间hh:mm:ss,表示飞行时间为hh小时mm分ss秒。

注意,当时间为一位数时,要补齐前导零,如三小时四分五秒应写为03:04:05。

数据范围

保证输入时间合法(0≤h≤23,0≤m,s≤59),飞行时间不超过24小时。

输入样例:

3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)

输出样例:

04:09:05
12:10:39
14:22:05

知识点 - sscanf、c_str、getline

知识传送门 -- sscanf

知识传送门 -- c_str

知识传送门 -- getline()

分析:

  1. 分析题意:

给定一趟航班的来回出发、到达的本地时间,但不知道两地的时差是多少,想知道真实的飞行时间

去:出发时间(t1) 到达时间(t2)

回:出发时间(t3) 到达时间(t4)

举例:

  • 北京 ==> 中东

    往西飞,飞行的时长是 相差的时间 + 时差

  • 中东 ==> 北京

    往东飞,飞行的时长是 相差的时间 - 时差

    那么

    • 相差的时间1 + 时差 = 相差的时间2 - 时差

    即(t2 - t1) - (t4 - t3) = 2时差

  1. 解题步骤:

    • 将所有的时间转化距离当天 00:00:00 的秒,方便计算时间的差值

    • 处理时间 time ,将秒数变为时分秒的形式

      hour = time / 3600

      minute = time % 3600 / 60

      second = time % 60

注意:此题需要掌握输入输出的技巧,还有一些字符串函数

代码(sscanf版本):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
​
using namespace std;
​
int get_second(int h,int m,int s)
{
    return h * 3600 + m * 60 + s; 
}
​
int get_time()
{
    string line;
    getline(cin,line);
    
    //将字符串格式全都转化为一样的 
    if(line.back() != ')') line += " (+0)";
    
    int h1,m1,s1,h2,m2,s2,d;
    //利用 c_str() 函数将string对象转换为 C 中的字符串样式 
    sscanf(line.c_str(), "%d:%d:%d %d:%d:%d (+%d)",&h1,&m1,&s1,&h2,&m2,&s2,&d);
    
    return get_second(h2,m2,s2) - get_second(h1,m1,s1) + d * 24 * 3600; 
}
​
int main()
{
    int n;
    scanf("%d",&n);
    
    //忽略第一行的回车 getchar()也行 
    string line;
    getline(cin,line); 
    //getchar();
​
    
    while(n --)
    {
        int time = (get_time() + get_time()) / 2;
        int hour = time / 3600;
        int minute = time % 3600 /60;
        int second = time % 60;
        printf("%02d:%02d:%02d\n",hour,minute,second);
    }
    
    
    return 0;
}

代码(scanf版本):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
​
using namespace std;
​
//scanf输入版本
int get_seconds(int h,int m,int s)
{
    return h*3600 + m*60 + s ;
}
​
int get_time()
{
    int h1,m1,s1,h2,m2,s2,d=0;
    scanf("%d:%d:%d %d:%d:%d (+%d)",&h1,&m1,&s1,&h2,&m2,&s2,&d);
    return get_seconds(h2,m2,s2) - get_seconds(h1,m1,s1) + d*24*3600;
    
}
​
int main()
{
    int n;
    scanf("%d",&n);
    
    while(n -- )
    {
        int time = (get_time() + get_time()) / 2;
        
        int hour = time / 3600;
        int minute = time / 60 % 60;
        int second = time % 60;
        printf("%02d:%02d:%02d\n",hour,minute,second);
    }
    
    return 0;
} 


06 - 外卖店优先级

题目传送门 -- 外卖店优先级

题目详情:

“饱了么”外卖系统中维护着 N 家外卖店,编号 1∼N。

每家外卖店都有一个优先级,初始时 (0 时刻) 优先级都为 0。

每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。

如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果优先级小于等于 3,则会被清除出优先缓存。

给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优先缓存中。

输入格式

第一行包含 3 个整数 N,M,T。

以下 M 行每行包含两个整数 ts 和 id,表示 ts 时刻编号 id 的外卖店收到一个订单。

输出格式

输出一个整数代表答案。

数据范围

1≤N,M,T≤10^5, 1≤ts≤T, 1≤id≤N,

输入样例:

2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

输出样例:

1

样例解释

6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6,加入优先缓存。

所以是有 1 家店 (2 号) 在优先缓存中。

题意分析:

输入

N: 维护的店子的数量

M: 平台在T时刻前收到的所有订单数量,订单信息包括下单单元时刻和下单店家的id号

T : T时刻之前收到的订单数量

输出:T时刻时优先缓存的店子的数量

代码(暴力写法)

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
​
using namespace std;
​
const int N = 20000;
int a[N][N];    //i 时刻 j 号店铺的订单情况,没有为 0 
bool st[N];     //是否在优先级缓存中 
int n,m,t;      //三个输入 
int score[N];   //店铺的优先级 
​
//暴力写法 - 可以过掉一部分 
int main()
{
    cin>>n>>m>>t;
    
    //输入m个订单信息 
    for(int i = 0;i < m; i ++)
    {
        int j,k;
        cin>>j>>k;
        a[j][k]++;
    }
    
    int res = 0;
    for(int i = 1;i < t + 1; i ++)
    {
        for(int j = 1; j < n + 1; j ++)
        {
            if(a[i][j] > 0){
                score[j] += a[i][j] * 2;
            }else{
                if(score[j]) score[j] -= 1;
            }
            if(score[j] > 5) st[j] = true;
            if(score[j] <= 3) st[j] = false;
            
//          cout<<score[j]<<" ";
        }
//      cout<<endl;
    }
    
    for(int i = 1;i <= n;i ++) res+=st[i];  
    cout<<res;
    return 0;
} 

优化版

变量解释:

score[i]:表示第i个店铺当前的优先级t[]

last[i] :表示第i个店铺上一次有订单的时刻

st[i] :表示第i个店铺当前是否处于优先级中

思路

假设某店铺拿到订单的时刻分别为t1, t2, t3, t4(假设已经按照非递减序排序),问第t4时刻店铺的优先级(根据题目t4>=t1,t2,t3) 解:

  • 总共需要计算2个部分:

    • 第一部分:1 ~ t1-1, t1+1 ~ t2-1, t2+1 ~ t3-1, t3+1 ~ t4-1, t4+1 ~ T,这几个部分是没有订单的时刻,需要减去这些个时刻

    • 第二部分:t1, t2, t3,t4 这几个时刻是接到接到订单的时刻,这几个时刻分别加2

  • 需要注意的是,如果同一时间有多个订单,假如上述的非递减序列中,t2 == t3,思路如下:

    • 第一部分:1 ~ t1-1, t1+1 ~ t2-1, t3+1 ~ t4-1, t4+1 ~ T,这几个部分是没有订单的时刻,需要减去这些个时刻

    • 第二部分:t1, t2, t4 这几个时刻是接到接到订单的时刻,这几个时刻分别加上该时刻订单数量cnt*2(cnt[t1] = 1, cnt[t2] = 2, cnt[t4] = 1)

  • 具体步骤:

    • 输入的m个订单信息,排序(时间 t 为第一优先级,订单 id 为第二优先级)

    • for 遍历订单信息(记得此时订单是按照时间顺序排的)。

    • 假设当前订单为第 i 个,循环判断后面有没有相同的订单(即 ts 和 id 相等)。(有的话一定连续)

    • 当到第 j 个时订单不相同,此时相同订单的数量为 cnt=j−i

    • 下一次for循环从 j 处开始遍历

    • 记录此时的t和id, 计算 该id 的优先权,有两部分

      • 第一部分,是上一个拿到订单的时间last[id]和t之间,中间没订单所以要−1,没订单的数量是 t−last[i]−1 (比如第3和第6时刻都有订单,没有订单的时候就是4,5)

      • 计算优先权,如果为负值更新为0。如果小于等于3,更新优先缓存 st[id]=falsest

      • 第二部分,是此时,t时刻拿到订单,并且拿到的数量为cnt,要加上2∗cnt

      • 计算优先权,如果大于5,更新优先缓存st[id]=true

    • 解释上面那个,因为此时这几个相同的订单都计算过了不需要再计算了,所以下一次循环要从j开始

    • 循环最后,上一次拿到订单的时间last[id]更新为t

    • 如果最后一个订单时刻为T,则没问题。如果不是T,那么最后一个拿到订单时刻到T时刻的这部分减法需要手动计算,即减去最后一个订单时刻与T的差值。换而言之,如果上一个拿到订单的时间last[id]小于T,则 优先权score 减去T−last[id]。注意这里不减1,因为T时刻也没订单。如果小于等于3,更新优先缓存

代码(优化版)

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
​
#define ts first
#define id second
​
using namespace std;
​
typedef pair<int,int> PII;
const int N = 100010;
bool st[N];     //是否在优先级缓存中 
int n,m,T;      //三个输入 
int last[N];
int score[N];   //店铺的优先级 
PII order[N];
​
int main()
{
    cin>>n>>m>>T;
    for(int i = 0; i < m; i ++) 
        scanf("%d%d",&order[i].ts,&order[i].id);
    sort(order,order + m);
    
    //只处理有订单信息的店铺
    //没有订单信息的店铺的优先级一直为零 
    for(int i = 0; i < m; )
    {
        int j = i;
        while(j < m && order[j] == order[i]) j++;
        
        int t = order[i].ts,id = order[i].id;
        int cnt = j - i;
        i = j;
        
        //第一部分 - 处理 t 之前的信息
        score[id] -= (t - last[id] - 1);
        if(score[id] < 0) score[id] = 0;
        if(score[id] <= 3) st[id] = false;
    
        
        //第二部分 - 处理 t 时刻的信息
        score[id] += cnt*2;
        if(score[id] > 5) st[id] = true; 
        
        last[id] = t;
    }
    
    for(int i = 1; i <= n; i ++)
    {
        if(last[i] < T)
        {
            score[i] -= T - last[i];
            if(score[i] <= 3) st[i] = false;
        }
    }
    
    int res = 0;
    for(int i = 0; i < m; i ++) res += st[i];
    cout<<res;
    
    return 0;
}

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值