8.3集训模拟赛总结

昨天偷了个懒没有发

这次也是考的特别好(cha)。。。

哎话不多说了,上题解把。

T1

1.  勇者们斗恶龙

题目ID:20301必做题100分

时间限制: 1000ms

空间限制: 524288kB

题目描述

恶龙又一次摧毁了城市,愤怒的国王决定讨伐恶龙。于是他在王国四处贴上告示,征召勇者们前来讨伐恶龙。

由于恶龙十分强大,勇者再厉害也只是凡人,一个人的力量是无法打败恶龙的,但团结起来的勇者们将是不可战胜的。恶龙的血量为X,X为整数。

每个勇士都有自己擅长的地方,都可以对某一阶段(某个血量区间内)的恶龙进行致命伤害。

现在国王要从n个勇士中选出可以完全覆盖对恶龙致命伤害的勇士,最少需要几个人?

输入格式

第一行输入一个n表示有n个勇士

第2行到第n+1行输入L和R,表示第i位勇士可以造成致命伤害的血量区间

第n+1行输入X表示恶龙的血量

输出格式

覆盖范围包括恶龙全部血量区间的数量,如果无法覆盖,则输出-1。

样例

Input 1

5 0 1 1 2 2 7 7 8 8 10 10

Output 1

5

样例解释

对每个TestSample的解释(为什么这个input会得到这个output)

数据范围

0 <= X <= 10^9

0 <= n <= 10000

题解

这题是一个区间覆盖问题(废话)

我们从区间的左端点开始进行遍历排序

​
#include<bits/stdc++.h>
#define int long long//10年OI一场空,不开long long见祖宗
using namespace std;
const int N = 1e4 + 10;
int n, x;
signed main()
{
	vector<pair<int, int>> q;//用结构体也可以
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		int a, b;
		cin >> a >> b;
		q.push_back({ a,b });
	}
	cin >> x;
	sort(q.begin(), q.end());//排序
	int r = 0, temp = 0, res = 0;
	for (int i = 0; i < n; i++)
	{
		if (temp >= x)//结束条件
		{
			cout << res << "\n";
			return 0;
		}
		if (q[i].first > temp)//不可以覆盖的情况输出-1
		{
			cout << "-1" << "\n";
			return 0;
		}
		while (i < n && q[i].first <= temp)
		{
			r = max(r, q[i].second), i++;
		}
		temp = r;
		res++;
		i--;
	}
	if (temp >= x)//再判断一遍是否合法
	{
		cout << res << "\n";
		return 0;
	}
	else
	{
		cout << -1 << "\n";
	}
	return 0;
}

​

T2

2.  社交树

题目ID:20316必做题100分

最新提交:

Accepted

100 分历史最高:

Accepted

100 分

时间限制: 1000ms

空间限制: 524288kB

题目描述

有一句话叫作:“最多只需要7个人就可以认识任何人”,因为每个人都有自己的朋友,而朋友也有自己的朋友,所以在这世界上的任何一个陌生人,可能都是你朋友的朋友的朋友的朋友的朋友的朋友的朋友。当然这并不意味着我们和任何一个陌生人建立联系很容易,通过朋友来找朋友往往需要花费不小的代价。现在你只有一个朋友,但你的朋友却有很多他的朋友(朋友是相互的,你也是他的朋友)。你和朋友进行联络需要付出一定的代价,同样的你朋友联络他的朋友也有一定的代价。给你所有的人和每个人的朋友关系,求出你联络他们每个人所需要的代价。

输入格式

第一行输入一个n表示有n个人

第二行输入n个整数ai​ (1<=i<=n),表示第i个人被他的朋友联络到需要的精力。a1​表示你联系你的朋友需要的精力。

随后n-1行每行两个数,表示这两个人是朋友。(输入保证朋友之间的关系网络不会形成环)。

输出格式

输出一行,共n个数,表示你联络到他们每个人需要花费的总精力。按第二行输入的顺序输出每个人的总精力。

样例

Input 1

5

1 2 3 4 5

1 2

1 3

2 4

2 5

Output 1

1 3 4 7 8

样例解释

输入的是一个树并且保证输入结构正确

数据范围

所有数据均不超过5000

题解

这道题一定要先手磨一下样例,就会发现这题是有多模板。。。

可以看到,我把样例中的树用手画出来了,这样就很好分析了,样例输出为1 3 4 7 8 

1就是根结点的权重,

3是从根结点1到2所花费的时间就是把题目的权重加起来,1 + 2

4和3一样

7是从根结点到4结点的时间,为1 + 2 + 4 = 7;

8同7;

这样分析下来,我们就会发现,遍历一遍树就完成了!

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, x, y;
bool  t[5010][5010];
int res[5005];
struct node 
{
	int x, y;
} q[5005];
void bfs(int s)
{
	int head = 1, tail = 1;
	q[head].x = 1;
	res[1] = q[head].y;
	tail++;
	while (head < tail) 
	{

		for (int i = 1; i <= n; i++)
		{
			if (t[q[head].x][i] == 1)
			{
				q[tail].x = i;
				tail++;
				res[i] = res[q[head].x] + q[i].y;

			}

		}
		head++;
	}
}
signed main()
{

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> q[i].y;
	}
	for (int i = 1; i < n; i++)
	{
		cin >> x >> y;
		t[x][y] = 1;
	}

	bfs(1);
	for (int i = 1; i <= n; i++)
	{
		cout << res[i] << " ";
	}
	return 0;
}

T3

T3还不太会,全网解答

时间限制: 1000ms

空间限制: 262144kB

题目描述

小信最近遇到了一道非常让他头疼的题目,如果有三个整数l,r,x(l≤r),cal(l,r,x)的定义如下:

  • 如果x<l:cal(l,r,x)=l−x
  • 如果l≤x≤r:cal(l,r,x)=0
  • 如果r<x:cal(l,r,x)=x−r

小信现在有N对整数,第i对表示为(Li​,Ri​),对于k=1,2,...,N,他可以任意选择一个整数x并计算cal(L1​,R1​,x),cal(L2​,R2​,x),...,cal(Lk​,Rk​,x)中的最大值,即max(cal(L1​,R1​,x),cal(L2​,R2​,x),...,cal(Lk​,Rk​,x))。对于每个k=1,2,...,N,请帮他找到每个k最小的max(cal(L1​,R1​,x),cal(L2​,R2​,x),...,cal(Lk​,Rk​,x))。

输入格式

第一行输入一个正整数N(1≤N≤2×105),表示整数对的个数。

接下来N行,每行两个正整数Li​和Ri​(1≤Li​≤Ri​≤109),表示一个整数对。

输出格式

输出N行,对每个k=1,2,...,N,每行输出一个整数,表示最小的max(cal(L1​,R1​,x),cal(L2​,R2​,x),...,cal(Lk​,Rk​,x))。

样例

Input 1
 

3 1 3 2 4 5 6

Output 1
 

0 0 1

Input 2
 

10 64 96 30 78 52 61 18 28 9 34 42 86 11 49 1 79 13 59 70 95

Output 2
 

0 0 2 18 18 18 18 18 18 21

样例解释

对于样例#1:

  • 1k=1时,可选1x=1。
  • 2k=2时,可选3x=3。
  • 3k=3时,可选4x=4。

数据范围

对于10%10%的数据,1≤N≤100,1≤Li​≤Ri​≤100。

对于20%20%的数据,1≤N≤1000,11≤Li​≤Ri​≤105。

对于100%100%的数据,1≤N≤105,1≤Li​≤Ri​≤109。

T4

题目ID:20296必做题100分

最新提交:

Accepted

100 分历史最高:

Accepted

100 分

时间限制: 2000ms

空间限制: 262144kB

题目描述

小信被给定两个整数 l 和 r,其中 l<r。从 l 开始,每次加 11 直到结果等于 r。每次加法操作会改变多少个数字的位数,并且改变的位数总是结果中的后缀部分。

例如:

如果l=909,则加一后得到 910910,会改变 22 个数字的位数;
如果 l=9,则加一后得到 1010,同样会改变 22 个数字的位数;
如果 l=489999,则加一后得到 490000490000,会改变 55 个数字的位数。

请输出每个测试用例中,从 l 到 r 的过程中总共改变了多少个数字的位数。

输入格式

第一行包含一个整数 t(1≤t≤104)。接下来有 t 个测试用例。

每个测试用例由两个整数 l 和 r 描述(1≤l<r≤109)。

输出格式

对于每个测试用例,计算从 l 开始加 11 直到达到 r 的过程中,总共改变了多少个数字的位数。

样例

Input 1

4 1 9 9 10 10 20 1 1000000000

Output 1

8 2 11 1111111110

数据范围

对于 10% 的数据,t≤10,r≤105
对于 20% 的数据,r≤105
对于 100% 的数据,无特殊限制。

题解

这题看到有点玄乎的样子,其实很简单,

开始设一个res = r - l;

然后两个循环,res分别减r/10和l/10就可以了(简单把)


#include<bits/stdc++.h>
#define int long long
using namespace std;
int l, r, t, res;
signed main()
{
	cin >> t;
	while (t--)
	{
		cin >> l >> r;
		res = r - l;
		for (;r > 0;)
		{
			res += r / 10;
			r /= 10;
		}
		for(;l > 0;)
		{
			res -= l / 10;
			l /= 10;
		}
		cout << res << endl;
	}
	return 0;
}

制作不易,点赞

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值