【区间贪心】P3661 [USACO17FEB] Why Did the Cow Cross the Road I S|普及+
本文涉及知识点
C++贪心
P3661 [USACO17FEB] Why Did the Cow Cross the Road I S
题目描述
Farmer John 的奶牛们正在学习如何有效地过马路。回想起古老的“鸡为什么要过马路?”笑话,他们认为鸡一定是过马路的专家,于是去寻找鸡来帮助它们。
事实上,鸡是非常忙碌的生物,它们只有有限的时间来帮助奶牛。农场上有 CCC 只鸡(1≤C≤20,0001 \leq C \leq 20,0001≤C≤20,000),方便地用编号 1…C1 \ldots C1…C 标识,每只鸡 iii 只愿意在确切的时间 TiT_iTi 帮助一头奶牛。奶牛们从不着急,它们的日程安排更加灵活。农场上有 NNN 头奶牛(1≤N≤20,0001 \leq N \leq 20,0001≤N≤20,000),方便地用编号 1…N1 \ldots N1…N 标识,其中奶牛 jjj 能够在时间 AjA_jAj 到时间 BjB_jBj 之间过马路。考虑到“伙伴系统”是最好的方式,每头奶牛 jjj 理想情况下希望找到一只鸡 iii 来帮助她过马路;为了使它们的日程安排兼容,iii 和 jjj 必须满足 Aj≤Ti≤BjA_j \leq T_i \leq B_jAj≤Ti≤Bj。
如果每头奶牛最多只能与一只鸡配对,每只鸡也最多只能与一头奶牛配对,请计算可以构建的最大奶牛-鸡配对数。
输入格式
输入的第一行包含 CCC 和 NNN。接下来的 CCC 行包含 T1…TCT_1 \ldots T_CT1…TC,接下来的 NNN 行包含 AjA_jAj 和 BjB_jBj(Aj≤BjA_j \leq B_jAj≤Bj),其中 j=1…Nj = 1 \ldots Nj=1…N。AAA、BBB 和 TTT 都是不超过 1,000,000,000 的非负整数(不一定互不相同)。
输出格式
请计算可能的奶牛-鸡配对的最大数量。
输入输出样例 #1
输入 #1
5 4
7
8
6
2
9
2 5
4 9
0 3
8 13
输出 #1
3
贪心
证明
奶牛的数据,按BI排序。我们迭代处理第0头奶牛,处理完后删除奶牛0。
如果没有鸡能教这头奶牛,删除此奶牛。
如果有鸡教第0头奶牛,教此奶牛是不劣解。某解奶牛0没有教,奶牛有教,换成教奶牛0,是不劣解。
如果多只鸡可以教奶牛0,则时间最小的鸡教。c1<c2,两只鸡都可以教奶牛0,c2教奶牛0,c1教奶牛i,交换一下是不劣解。
c2能教奶牛0,说明a0 <= c2 <= b0 <=bi , c1能教奶牛i,说明 ai<=c1,结合c1 <=c2。→\rightarrow→ ai <= c2 <=bi。即c2可以教奶牛i。
解法
多键有序集合s,记录T。AI,BI按BI排序。
it = s.lower(AI)
如果it > BI,忽略,否则{
ans++; s中删除it
}
代码
核心代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>#include <bitset>
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T = int>
vector<T> Read() {int n;scanf("%d", &n);vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行 return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1,class T2>inline CInBuff& operator>>(pair<T1,T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2,class T3>inline CInBuff& operator>>(tuple<T1, T2,T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3,class T4>inline CInBuff& operator>>(tuple<T1, T2, T3,T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for(int i = 0 ;i < canRead;i++){buffer[i] = S[i];//memcpy出错 }m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};class CNeiBo
{
public:static vector<vector<int>> Two(int n, vector<pair<int, int>>& edges, bool bDirect, int iBase = 0){vector<vector<int>> vNeiBo(n);for (const auto& [i1, i2] : edges){vNeiBo[i1 - iBase].emplace_back(i2 - iBase);if (!bDirect){vNeiBo[i2 - iBase].emplace_back(i1 - iBase);}}return vNeiBo;}static vector<vector<int>> Two(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0){vector<vector<int>> vNeiBo(n);for (const auto& v : edges){vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase);if (!bDirect){vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase);}}return vNeiBo;}static vector<vector<std::pair<int, int>>> Three(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0){vector<vector<std::pair<int, int>>> vNeiBo(n);for (const auto& v : edges){vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);if (!bDirect){vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);}}return vNeiBo;}static vector<vector<int>> Mat(vector<vector<int>>& neiBoMat){vector<vector<int>> neiBo(neiBoMat.size());for (int i = 0; i < neiBoMat.size(); i++){for (int j = i + 1; j < neiBoMat.size(); j++){if (neiBoMat[i][j]){neiBo[i].emplace_back(j);neiBo[j].emplace_back(i);}}}return neiBo;}
};class Solution {
public:int Ans(vector<int>& t, vector<pair<int, int>>& ab){sort(ab.begin(), ab.end(),[&](const pair<int, int>& pr1, const pair<int, int>& pr2) {return pr1.second < pr2.second; });multiset<int> s(t.begin(), t.end());int ans = 0;for (const auto& [a, b] : ab) {auto it = s.lower_bound(a);if ((s.end() == it) || (*it > b)) { continue; }ans++; s.erase(it);}return ans;}
};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG CInBuff<> ib;int n, m;ib >> n >> m ;auto t = ib.Read<int>(n);auto ab = ib.Read<pair<int, int>>(m);
#ifdef _DEBUG //printf("N=%d,", n);Out(t, ",t=");Out(ab, ",ab=");/*Out(edge, "edge=");Out(que, "que=");*/
#endif // DEBUG auto res = Solution().Ans(t,ab);cout << res;return 0;
}
单元测试
vector<int> t;vector<pair<int, int>> ab;TEST_METHOD(TestMethod1){t = { 3,4 },ab = { {1,5},{3,3} };auto res = Solution().Ans(t, ab);AssertEx(2, res);}TEST_METHOD(TestMethod2){t = { 3,3 }, ab = { {1,5},{3,3} };auto res = Solution().Ans(t, ab);AssertEx(2, res);}TEST_METHOD(TestMethod11){t = { 7,8,6,2,9 }, ab = { {2,5},{4,9},{0,3},{8,13} };auto res = Solution().Ans(t, ab);AssertEx(3, 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++**实现。