昨天偷了个懒没有发
这次也是考的特别好(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;
}