本博文代码打包下载
C++贪心
C++二分查找
C++算法:滑动窗口及双指针总结
【题目描述】
您正在参加一场团体越野比赛。您的队伍共有 n n n 名队员,其中第 i i i 名队员的速度为 v i v_i vi,体重为 w i w_i wi。
比赛允许每名队员独立行动,也允许一名队员背着另一名队员一起行动。当队员 i i i 背着队员 j j j 时,如果队员 i i i 的体重大于等于队员 j j j,则队员 i i i 的移动速度不会变化,仍然为 v i v_i vi;如果队员 i i i 的体重小于队员 j j j,则队员 i i i 的移动速度会减去两者的体重差值,即变为 v i − ( w j − w i ) v_i - (w_j - w_i) vi−(wj−wi)。如果队员 i i i 的移动速度将变为负数,则队员 i i i 无法背起队员 j j j。每名队员最多只能背负另一名队员,被背负的队员无法同时背负其他队员。
所有未被背负的队员中,最慢的队员的速度,即为整个队伍的速度。求整个队伍能达到的最大速度。
【输入格式】
有多组测试数据。第一行输入一个整数 T T T 表示测试数据组数,对于每组测试数据:
第一行输入一个整数 n n n( 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1≤n≤105)表示队员人数。
对于接下来 n n n 行,第 i i i 行输入两个整数 v i v_i vi 和 w i w_i wi( 1 ≤ v i , w i ≤ 1 0 9 1 \le v_i, w_i \le 10^9 1≤vi,wi≤109)表示第 i i i 名队员的速度和体重。
保证所有数据中 n n n 之和不超过 1 0 5 10^5 105。
【输出格式】
每组数据输出一个整数,表示整个队伍可以达到的最大速度。
【样例解释】
样例数据的最优策略如下:
因此答案为 8 8 8。
2
5
10 5
1 102
10 100
7 4
9 50
2
1 100
10 1
8
1
The optimal strategy for the sample test case is shown as follows:
So the answer is 8 8 8.
二分类型:寻找尾端
参数范围:[最小速度,最大速度]
Check函数:能否让所有队员速度都大于等于mid,速度小于mid的队员需要人背,且背后的速度大于等于mid。
令x1是速度不达标,体重最轻的队员。则背他的队友一定是:速度达标,且速度 + 体重 - x1体重 >= mid,如果有多个符合,取速度+体重最小的。不符合的队友,不能背任何队友,故淘汰。
v1记录所有队友的体重和速度,升序。
v2记录所有队员的速度+体重,速度。
j=0
for i1,i2 v1
如果速度大于等于mid忽略
寻找 v2[j]的速度大于等于mid,速度 + 体重 - x1体重 >= mid。如果找不到,返回false
由于j不复位,故Check函数的时间负重度是O(n)。
总时间复杂度:O(nlongn)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
template<class T = int>
vector<T> Read(int n,const char* pFormat = "%d") {
vector<T> ret;
T d ;
while (n--) {
scanf(pFormat, &d);
ret.emplace_back(d);
}
return ret;
}
template<class T = int>
vector<T> Read( const char* pFormat = "%d") {
int n;
scanf("%d", &n);
vector<T> ret;
T d;
while (n--) {
scanf(pFormat, &d);
ret.emplace_back(d);
}
return ret;
}
string ReadChar(int n) {
string str;
char ch;
while (n--) {
do
{
scanf("%c", &ch);
} while (('\n' == ch));
str += ch;
}
return str;
}
template<class INDEX_TYPE>
class CBinarySearch
{
public:
CBinarySearch(INDEX_TYPE iMinIndex, INDEX_TYPE iMaxIndex) :m_iMin(iMinIndex), m_iMax(iMaxIndex) {}
template<class _Pr>
INDEX_TYPE FindFrist(_Pr pr)
{
auto left = m_iMin - 1;
auto rightInclue = m_iMax;
while (rightInclue - left > 1)
{
const auto mid = left + (rightInclue - left) / 2;
if (pr(mid))
{
rightInclue = mid;
}
else
{
left = mid;
}
}
return rightInclue;
}
template<class _Pr>
INDEX_TYPE FindEnd(_Pr pr)
{
int leftInclude = m_iMin;
int right = m_iMax + 1;
while (right - leftInclude > 1)
{
const auto mid = leftInclude + (right - leftInclude) / 2;
if (pr(mid))
{
leftInclude = mid;
}
else
{
right = mid;
}
}
return leftInclude;
}
protected:
const INDEX_TYPE m_iMin, m_iMax;
};
class Solution {
public:
int MaxV(vector<int>& v, vector<int>& w) {
const int N = v.size();
vector<pair<int, int>> v1, v2;
for (int i = 0; i < N; i++) {
v1.emplace_back(w[i], v[i]);
v2.emplace_back(w[i] + v[i], v[i]);
}
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
auto Check = [&](int mid) {
for (int iii = 0, j = 0; iii < N; iii++) {
if (v1[iii].second >= mid) { continue; }
bool can = false;
for (; j < N; j++) {
if (v2[j].second < mid) { continue; }
if (v2[j].first - v1[iii].first >= mid) { can = true; break; }
}
if (!can) { return false; }
j++;
}
return true;
};
const int iMax = *max_element(v.begin(), v.end());
CBinarySearch bs(0, iMax);
return bs.FindEnd(Check);
}
};
int main() {
#ifdef _DEBUG
freopen("a.in", "r", stdin);
#endif // DEBUG
int T = 0;
scanf("%d", &T);
for (int i = 0; i < T; i++)
{
int n;
scanf("%d", &n);
vector<int> v, w;
int t1, t2;
for (int j = 0; j < n; j++) {
scanf("%d%d", &t1, &t2);
v.emplace_back(t1);
w.emplace_back(t2);
}
auto res = Solution().MaxV(v, w);
cout << res << std::endl;
}
return 0;
}
vector<int> v, w;
TEST_METHOD(TestMethod11)
{
v = { 10,1,10,7,9 }, w = { 5,102,100,4,50 };
auto res = Solution().MaxV(v, w);
AssertEx(8, res);
}
TEST_METHOD(TestMethod12)
{
v = { 1,10}, w = { 100,1 };
auto res = Solution().MaxV(v, w);
AssertEx(1, res);
}
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。