问题描述
疫情使得人们线下社交隔离,进而刺激了宅娱乐经济,令手机游戏市场份额再次创新纪录。一款手机游戏一般有很多角色,每个角色都可以设定一个战力值。为了平衡每个角色的能力,提升玩家的游戏体验,游戏策划往往会对角色的战力值通过一些规则进行限制。
在某款手游里共有 n
个角色。这些角色从 0
到 n-1
进行编号排成一列。角色的战力值按照以下的规则进行限定:
- 第一个角色的初始战力值为
0
- 每个角色的战力值是一个非负的整数
- 相邻角色的战力值差距不能超过
1
(之间的差值可能是0
,+1
,-1
)
在上边规则的基础上会再额外对其中的一些角色增加一些限制,设定最大战力值。这些限制会以若干数对的形式给出,每一个数对定义如下,limit[i] = [index, maxPower]
(index != 0
且 i < n - 1
)表示编号为 index
的角色的最大战力值不能超过 maxPower
(maxPower
为一个非负整数)。由于第一个角色有了初始的战力值,所以不会再对编号为 0
的角色进行战力值限定。
请根据以上规则,计算出单个角色能达到的最大战力值。
输入格式
第一行为两个整数 n,m (2<=n<=10^6, 1<=m<=10^5),其中 n 为游戏中角色的总个数,m 为限制了最大战力值的角色数。
后边的 m 行,每一行都有两个整数 index, maxPower (index != 0 且 index < n - 1),index 是角色编号,index != 0 即不会对编号为 0 的角色进行战力值的限定,maxPower 是该角色被限定的最大战力值。
输出格式
输出1个整数,表示单个角色能达到的最大战力值。
输入样例1
3 2
1 3
2 2
说明:
第1行表示游戏中有3个角色,对其中2个角色限制了最大战力值。
接下来的2行是具体的限制,对编号为1的角色限制了最大战力值为3,对编号为2的角色限制了最大战力值为2。
输出样例1
2
说明:
[0,1,2]
是满足规则约束的一个战力值设定方案,相邻角色的战力值之差不超过 1
,最大战力值是最后一个角色,最大战力值为 2
。
输入样例2
5 3
1 1
2 3
4 3
说明:
第1行表示游戏中有5个角色,对其中3个角色限制了最大战力值。
接下来的2行是具体的限制,对编号为1的角色限制了最大战力值为1,对编号为2的角色限制了最大战力值为3,对编号为4的角色限制了最大战力值为3。
输出样例2
3
说明:
[0,1,2,3,3]
是满足规则约束的一个战力值设定方案,相邻角色的战力值之差不超过 1
,最大战力值是最后两个角色,最大战力值为 3
。
数据范围
2 ≤ n ≤ 1 0 6 1 ≤ m ≤ 1 0 5 2 \leq n \leq 10^6 \\ 1 \leq m \leq 10^5 2≤n≤1061≤m≤105
思路
去掉题目描述的角色外壳剖析内在,实质上就是一道求前后关联数据问题求解。思路是这样,正向走一遍,再返回来走一遍。第一遍走的时候,我们定义一个power数组,限制处接受样例给定的最大战力,power[0]为0,其余为INT_MAX,在第一遍正向即从左往右遍历时,转移方程为power[i]=min(power[i-1] + 1, power[i])
,为什么会使用min()
?因为要保证符合限制,也就是power[i]为非INT_MAX时,该下标的实际战力值要尽可能地小地来通过限制条件。那么,使用该转移方程跑一遍,我们只能得到不断上升地战力值,但是遇到限制条件min()
会毫不犹豫地选择限制条件,或者是合法的通过有限制的下标,这时,我们需要反向再次遍历。反向遍历就是正向的逆过程,这里先上转移方程,先脑内构思一下power[i] = min(power[i], power[i + 1] + 1)
。在这个过程内,如果某段在两限制点间的战力值的斜率为1或者0,那么不会对这段战力值改变,但是遇到了限制条件,方程就会消除正向遍历产生的断层。最后,我们就得到了尽可能大地而又合法地战力数组了。
源码
CPP
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int solution(int n, int m, vector<vector<int>>& array) {// Edit your code herevector<int> power(n, INT_MAX);//更新限制条件for (int i = 0; i < m; i++) {int index = array[i][0];int maxPower = array[i][1];power[index] = min(power[index], maxPower);}//初始化第一个角色的战力值power[0] = 0;//计算每个角色的最大战力值for (int i = 1; i < n; i++) {//计算当前角色的最大战力值power[i] = min(power[i], power[i - 1] + 1);}//再次正向传播限制条件for (int i = n - 2; i >= 0; i--) {power[i] = min(power[i], power[i + 1] + 1);}//返回最大的战力值int maxPower = 0;for (int p : power) {maxPower = max(maxPower, p);}return maxPower;
}int main() {// Add your test cases herevector<vector<int>> sample1 = {{1, 3}, {2, 2}};vector<vector<int>> sample2 = {{1, 1}, {2, 3}, {4, 3}};cout << solution(3, 2, sample1) << endl; //output:2cout << solution(5, 3, sample2) << endl; //output:3return 0;
}