2021-TKK-ICPC Summer Training Camp Round #1

1:消灭星星
时间限制: 1 S | 内存限制: 65536 KB
Accept: 0 | Submit: 0

反卷局局长在玩消灭星星,一大堆星星按顺序竖直放进管道里,他有m次消灭星星的机会,每次都可以消灭一段连续且颜色相同的星星,如果下面的星星被消灭了,上面的星星就会因为重力而落下,现在为了优化难度,只有两种颜色的星星,0代表红色星星,1代表黄色星星,反卷局局长想问能否在给定的次数清空所有的星星?

输入
多组案例。一个正整数T,表示案例的数量。(T<=50)

每组案例先是两个正整数n和m,分别代表星星的总数和消灭星星的机会。(n<=1e5,m<=1e5)

然后按顺序给出n个整数,A1、A2、…、An。整数值代表星星的颜色(Ai=0 或 Ai=1),星星在竖直管道里的位置根据数字出现的先后,A1在最下面,A2在A1的上面…An在最顶端。

输出
针对每组案例,如果能够在给定的机会次数以内清空完星星,输出YES,否则输出NO

每组案例输出完都要换行。

样例输入
2

5 2

0 1 1 1 0

4 2

0 1 0 1

样例输出
YES

NO

HINT
样例1:第一步消灭中间的三颗星星[0,1,1,1,0] =>[0,0],第二步消灭剩余的两颗[0,0]=>[]、

样例2:两次操作无法消灭所有的星星

来源
2021-TKK-ICPC Summer Training Camp Round #1
只要考虑有多少给’块‘与块中个数无关
即 只需考虑
0 1 10 01 101 010此类
同样说明与01次序无关


int a[100001],;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		int t,num=1;
		cin >> t;
		for (int i = 1; i < n; ++i)
		{
			int e;
			cin >> e;
			if (e != t)
			{
				num++;
				t = e;
			}
		}
		if (num / 2 + 1 > m)
			cout << "NO\n";
		else
			cout << "YES\n";
	}
	return 0;
}

2
2:下馆子-3
时间限制: 1 S | 内存限制: 65536 KB
Accept: 0 | Submit: 0
每学期信息学院都会组织的下馆子活动,城城是下馆子的工作人员,城城看到勤奋的学子,特别感动,就会额外给他增加出勤次数。但罗少黑入了系统,有时候心情不好,就会随意挑选一名同学,减少这位同学的出勤次数。到最后信息学院为了找到签到次数最多的那个人,从后台按时间顺序获取了n条操作信息。请你帮他们找到最终签到次数最多的那个人,如果存在多个人,即他们的次数都为max次,请输出出勤次数最先大于等于max次的同学。

输入
只有一组案例

第一行是一个正整数 n 代表总共有 n 次操作记录。(1 <= n <= 1e5)

总共n 行,每行由name,time组成。分别代表同学的名字,和出勤次数的变化(负数是减少,正数是增加)。 ( -500<=time<=500)

保证每个名字的字符不会超过 30,输入的顺序即为签到的先后。

输出
输出最终签到次数最多的那个人,如果存在多个人,即他们的次数都为max次,请输出出勤次数最先大于等于max次的同学,最后一行不要换行

样例输入
5

xinyugiegie 1

fxw 4

xinyugiegie -1

fxw -2

xinyugiegie 2

样例输出
fxw

HINT
最后有两位同学到达2次,由于fxw的出勤次数曾经最先大于等于2次因此输出fxw
模拟
考虑多个最大值时在搭建过程中出现更大值的情况

struct li {
	string name;
	int d;
}list[100000];

map<string, long long>c,c1;
int main()
{
	int k = 0;
	string mname;
	int maxn=-500000000;
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i)
	{
		cin >> list[i].name >> list[i].d;
		c[list[i].name]+=list[i].d;
	}

	for (map<string, long long>::iterator it = c.begin(); it != c.end(); it++)
	{
		if (it->second > maxn)
		{
			maxn = it->second;
			mname = it->first;
			k = 0;
		}
		else if (it->second == maxn)
		{
			++k;
		}
	}
	if (k == 0)
	{
		cout << mname ;
		return 0;
	}
else
for (int i = 0; i < n; ++i)
{
	c1[list[i].name] += list[i].d;
	if (c1[list[i].name] >= maxn)
	{
		cout << list[i].name;
		return 0;
	}
}
	return 0;
}

1584:光照强度-2
时间限制: 1 S | 内存限制: 65536 KB
Accept: 3 | Submit: 48
有一个长方形的房间,可以近似地看成由a行b列的方格构成。最开始,房间里每个位置的亮度为0。

在房间里共有m盏灯,每个位置可以放多盏灯。每盏灯有一定的光照强度c,可以给房间里的每个位置提供一定的亮度,但随着距离增加,提供的亮度会相应减少。

假设灯在位置(x1,y1),其光照强度为c,那么此灯对位置(x2,y2)的亮度的贡献值为

当房间里不止一盏灯的时候,照亮效果不可以叠加,某位置的的亮度为所有灯提供的亮度的最大值。

例如下图是一个3行3列的房间,在第1行第1列有一盏光照强度为3的灯,在第3行第3列有一盏光照强度为4的灯,整个房间的明亮度分布如下。

第2行第2列的亮度由两盏灯提供,但第3行第3列的灯提供的亮度更高,因此此位置的亮度为2。

请输出整个房间的明亮程度分布。

输入
一组案例。

首先是三个正整数a、b、m,表示房间有a行b列,有m盏灯。(a<=1000,b<=1000,m<=10000)

然后是m行数据,每行数据有3个正整数x、y、c,表示某一盏灯位于第x行第y列,光照强度为c。(左上角称为第1行第1列,1<=x<=a,1<=y<=b,1<=c<=100000)

输出
针对每组案例,依次输出每一格的亮度,每两个数字之间留一个空格,每行结束后要换行。

样例输入
3 3 2

1 1 3

3 3 4

样例输出
3 2 2

2 2 3

2 3 4
因为c过大直接搜索会tle
因为光线像四个方向递减即可以逆向思维认为位置从四周接收光线
有点类似积水问题的二维版

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int map[1003][1003] = { 0 };
int main()
{
	int a, b, m;
	cin >> a>>b>>m;
	for (int i = 0; i < m; ++i)
	{
		int x, y, c;
		cin >> x >> y >> c;
		map[x][y] = max(c,map[x][y]);
	}
	
	//x y
	for (int i = 1; i <= a; ++i)
		for (int j=1; j <= b; ++j)
			map[i][j] = max(map[i][j], max(0, max(map[i-1][j ] - 1, map[i][j - 1]-1)));
	//x -y	
	 for (int i=1; i <= b; ++i)
		 for (int j = b; j >0; --j)
		     map[i][j] = max(map[i][j], max(0, max(map[i-1][j]-1,map[i][j+1]-1)));
	//-x y
	for (int i = a; i >0; --i)
		for (int j = 1; j<=b; ++j)
			map[i][j] = max(map[i][j], max(0, max(map[i+1][j]-1,map[i][j-1]-1)));
	//-x -y
	for (int j =b; j >0; --j)
		for (int i=a; i >0; --i)
			map[i][j] = max(map[i][j], max(0, max(map[i + 1][j]-1,map[i][j+1]-1)));
	for (int i = 1; i <= a; ++i)
	{
		for (int j = 1; j < b; ++j)
			cout << map[i][j] << ' ';
		cout << map[i][b] << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值