ACM模板一:线性表、栈、队列、背包

目录

〇,全文说明、宏定义代码

一,输入输出

二,vector

三,链表

四,STL操作封装、拓展数据结构、背包

五,test


〇,全文说明、宏定义代码

类里面和宏定义处都有接口注释,因为宏不体现具体参数,所以注释以类里面的为准。

所有代码放在一起是可以编译运行的,如果按照章来划分,最后一章是测试代码,其他任意一章都可以单独编译运行

ACM模板一:线性表、栈、队列、背包_第1张图片

宏定义代码:


#define LOCAL //力扣不要本行代码,其他OJ随意

///(1)输入输出///
#define Print(x) cout << endl << #x << " = "; INOUT::print(x);//输出数据
#define Read(x) INOUT::read(x);//读入数据

///(2.1)容器基本计算
#define FvecJoin Basic::fvecJoin //2个vector(一维或2维)左右拼接起来
#define Frev Basic::frev//翻转vector、翻转二维vector的每一行

///(2.2)单vector操作///
#define Foverturn SingleVectorOpt::foverturn//沿主对角线(左上角到右下角)翻转二维vector
#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define DeletAllX SingleVectorOpt::deletAllX//从vector(一维或2维)中删除所有的x
#define GetDifNum SingleVectorOpt::getDifNum//判断有序数组中有多少个不同的数
#define Fcheng SingleVectorOpt::fcheng//vector乘一个数
#define Fjia SingleVectorOpt::fjia//vector加一个数
#define SortEveryLine SingleVectorOpt::sortEveryLine//二维数组每一行排序
#define FirstInLeft SingleVectorOpt::firstInLeft//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
#define Fminlef SingleVectorOpt::fminlef//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
#define Fminlef2 SingleVectorOpt::fminlef2//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
#define Fmaxlef SingleVectorOpt::fmaxlef//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
#define Fmaxlef2 SingleVectorOpt::fmaxlef2//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
#define Fminrig SingleVectorOpt::fminrig//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
#define Fminrig2 SingleVectorOpt::fminrig2//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
#define Fmaxrig SingleVectorOpt::fmaxrig//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
#define Fmaxrig2 SingleVectorOpt::fmaxrig2//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1

///(2.3)vector拆分拼接、择优合并///
#define VecSplit VectorJoin::vecSplit//把v分成前面k个和后面的v.size()-k个,返回拆出来的后面的数组,v本身只留k个
#define LoopSplit VectorJoin::loopSplit//把{1,2,3,4,5,6,7}循环拆分成{1,4,7}{2,5}{3,6}
#define CrossChange VectorJoin::crossChange//交叉交换,v1分成前面k1个和后面的v1.size()-k1个,v2同理,交换后面的2段
#define MergeVector VectorJoin::mergeVector //vector的择优合并
#define FoldJoin VectorJoin::foldJoin//二维vector拼接转化成一维的
#define SelfCopyJoin VectorJoin::selfCopyJoin//把vector自复制一份,前后拼接起来

///(2.4)vector的索引、数据域拓展和提取、拓展排序、逆置换///
#define Fshr VectorOpt::fshr//收缩计数,把[1 4 4 1]变成[(1,2)(4,2)]或[(1,1)(4,2)(1,1)]
#define Funshr VectorOpt::funshr//平摊,把 [(1,2)(4,2)]变成[1 1 4 4]
#define Foreach VectorOpt::foreach//生成枚举序号
#define ChangeMeiJu VectorOpt::changeMeiJu//根据各数字对应的替换列表,生成各种替代枚举
#define SubMeiJu VectorOpt::subMeiJu //根据各id对应的替换列表,生成各种替代枚举
#define Expand VectorOpt::expand //拓展数据域,加上id
#define SortWithId VectorOpt::sortWithId//给vector拓展,加上id并拓展成稳定排序
#define SortId VectorOpt::sortId//排序后数组中的每个数的原ID,输入8 5 6 7,输出1 2 3 0
#define SortId2 VectorOpt::sortId2//每个数在排序后的数组中的ID,输入8 5 6 7,输出3 0 1 2
#define SortExtend VectorOpt::sortExtend//给v排序,v2按照同样的顺序调整,输入{1,3,2}{4,5,6},输出{1,2,3}{4,6,5}
#define FindSum VectorOpt::findSum//2个vector中寻找和为s的对,返回结果的每一行都是[id1,id2]
#define CmpVector VectorOpt::cmpVector//vector的字典序比较,v1=v2是false
#define SortVector VectorOpt::sortVector//vector的字典序排序

///(2.5)vector的计算///
#define VecAdd VectorCal::vecAdd//2个vector相加
#define EverySum VectorCal::everySum//枚举2个vector的两数之和
#define IsSame VectorCal::isSame//判断2个vector(一维或二维)是否全等
#define DeleteSameLine VectorCal::deleteSameLine//二维数组去掉重复行
#define HaveSameData VectorCal::haveSameData//判断vector中是否含有重复元素
#define DeleteLineWithSameDatas VectorCal::deleteLineWithSameDatas//删除二维vector中,含有重复元素的行
#define VecConvolution VectorCal::vecConvolution//2个vector的卷积

///(3.1)单链表///
#define InitLinkList LinkList::initLinkList//构建链表
#define OutLinkList LinkList::outLinkList//打印链表
#define GetLength LinkList::getLength//获取链表长度
#define IsSameLinkList LinkList::isSameLinkList//两个链表的数据是否全等
#define Reverse LinkList::reverse//链表反转,返回新的head
#define GetKthFromEnd LinkList::getKthFromEnd//链表中倒数第k个节点
#define GetTail LinkList::getTail//链表最后一个节点
#define LinkSplit LinkList::linkSplit//留下前k个节点,把后面的切下来并返回
#define LinkMerge LinkList::linkMerge//直接合并2个链表
#define MergeTwoLists LinkList::mergeTwoLists//把两个链表交叉合并为一个链表
#define MergeTwoUpLists LinkList::mergeTwoUpLists//把两个升序的链表合并为一个升序的链表
#define ListToVec LinkList::listToVec//把链表转化成结构体指针数组
#define VecToList LinkList::vecToList//把结构体指针数组转化成链表
#define SortLinkList LinkList::sortLinkList//链表排序
#define GetAnyoneInCycle LinkList::getAnyoneInCycle//求链表环中任意节点,没环返回NULL
#define GetFirstInCycle LinkList::getFirstInCycle//求链表环的第一个节点,没环返回NULL
#define GetCycleLen LinkList::getCycleLen//求链表环的长度,没环返回0

///(3.2)双向循环链表///
#define GetSingleDeList DeLinkList::getSingleDeList//创建单节点双向循环链表
#define MergeDelist DeLinkList::mergeDelist//合并双向循环链表
#define GetLengthOfDeLL DeLinkList::getLengthOfDeLL//获取链表长度


///(4.1)STL操作封装
#define VecGet StlBasicOpt::vecGet//获取列表某处的值
#define Finsert StlBasicOpt::finsert//id处覆盖或者添加一个数
#define DelOnlyOne StlBasicOpt::delOnlyOne//multi***容器x删除一个数值n
#define DelEnd StlBasicOpt::delEnd//删除最后一个元素

///(4.2)拓展数据结构///
#define VecGet StlBasicOpt::vecGet//获取列表某处的值
#define Finsert StlBasicOpt::finsert//id处覆盖或者添加一个数
#define DelOnlyOne StlBasicOpt::delOnlyOne//multi***容器x删除一个数值n
#define DelEnd StlBasicOpt::delEnd//删除最后一个元素
// MonotonicStack 略。单调栈
// MinMaxStack 略。栈的拓展,支持获取最值,所有接口时间复杂度都是 O(1)
// MinMaxStack2 略。栈的拓展,支持删除最值,所有接口时间复杂度都在 O(log n)之内
// MonotonicQueue 略。单调队列
// MinMaxQueue 略。队列的拓展,支持获取最值,所有接口的均摊时间复杂度都是O(1)
// QueueWithNoSameData 略。不含重复元素的队列

///(4.3)背包///
//Pack 略。01背包、完全背包、多重背包、混合背包
//PackDoubleVolume 略。双代价背包
//PackGroup 略。分组背包
//PackGeneralize 略。泛化物品背包
//PackDepend 略。依赖背包(仅限森林)

一,输入输出


//对输入输出进行了封装,利用重载让各种数据结构的输入输出都可以用统一的函数名,同时让输入和输出匹配。
//注意顺序是:基本数据类型、不含容器的自定义数据结构、容器、含容器的自定义数据结构。
const float theNan = 0.123456;  //float默认输出只有6位
class INOUT
{
public:
	//(1)基本类型
	template
	static inline void print(T x)
	{
		cout << x << " ";
	}
	template
	static inline void read(T& x)
	{
		while (!(cin >> x)) { // only cin type T, ignore other info
			cin.clear();
			cin.ignore();
		}
	}
	static void print(float x)
	{
		if (std::isnan(x)) cout << theNan << " ";
		else cout << x << " ";
	}
	static void read(float& x)
	{
		read(x);
		if (x == theNan) x = NAN;
	}
	// (2)不含容器的自定义数据结构
	//(3)容器
	template
	static inline void print(const std::pair& p)
	{
		print(p.first);
		print(p.second);
	}
	template
	static inline void print(const map& aMap)
	{
		cout << " size = " << aMap.size() << endl;
		for (auto& it : aMap) {
			print(it);
			cout << endl;
		}
	}
	template
	static inline void print(const vector& vec)
	{
		cout << " size = " << vec.size() << endl;
		for (auto& it : vec) {
			print(it);
		}
		cout << endl;
	}
	template
	static inline void read(std::pair& p)
	{
		read(p.first);
		read(p.second);
	}
	template
	static void read(std::map& aMap)
	{
		int num;
		read(num);
		std::pair p;
		while (num--) {
			read(p);
			aMap[p.first] = p.second;
		}
	}
	template
	static inline void read(vector& vec)
	{
		int num;
		read(num);
		vec.resize(num); // 慎用
		for (int i = 0; i < num; i++) {
			read(vec[i]);
		}
	}
	//(4)含容器的自定义数据结构
};

二,vector

class Basic {
public:
	//2个vector(一维或2维)左右拼接起来
	template
	static vector fvecJoin(const vector& v1, const vector& v2)
	{
		vectorans(v1.size() + v2.size());
		copy(v1.begin(), v1.end(), ans.begin());
		copy(v2.begin(), v2.end(), ans.begin() + v1.size());
		return ans;
	}
	template
	static vector> fvecJoin(const vector>& v1, const vector>& v2)
	{
		vector>ans;
		ans.resize(v1.size());
		for (int i = 0; i < v1.size(); i++)ans[i] = join(v1[i], v2[i]);
		return ans;
	}
	//翻转vector、翻转二维vector的每一行
	template
	static vector frev(const vector& v)
	{
		vector ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
		return ans;
	}
	template
	static vector> frev(const vector>& v)
	{
		vector>ans;
		for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
		return ans;
	}
};
class SingleVectorOpt :public Basic
{
public:
	//沿主对角线(左上角到右下角)翻转二维vector
	template
	static vector> foverturn(const vector>& v)
	{
		vector> ans(v[0].size());
		for (int i = 0; i < v[0].size(); i++) {
			ans[i].resize(v.size());
			for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
		}
		return ans;
	}
	//顺时针旋转二维vector
	template
	static vector> frotation(const vector>& v)
	{
		return frev(foverturn(v));
	}
	//从vector(一维或2维)中删除所有的x
	template
	static void deletAllX(vector& v, T x)
	{
		for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
	}
	template
	static void deletAllX(vector>& v, T x)
	{
		for (auto& vi : v)deletAllX(vi, x);
	}
	//判断有序数组中有多少个不同的数
	template//T可以是指针或迭代器,统计范围是[left,right)
	static int getDifNum(T left, T right)
	{
		if (left == right)return 0;
		int ans = 1;
		for (T it = left + 1; it != right; it++)ans += *it != *(it - 1);
		return ans;
	}
	template
	static int getDifNum(vectorv)
	{
		return getDifNum(v.begin(), v.end());
	}
	//vector乘一个数
	template
	static void fcheng(vector& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
	}
	//vector加一个数
	template
	static void fjia(vector& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
	}
	//二维数组每一行排序
	template
	static void sortEveryLine(vector>& v)
	{
		for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
	}
	//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
	template
	static inline vectorfirstInLeft(vectorv, P pr)
	{
		vector ans;
		if (v.size() == 0)return ans;
		stackst;
		st.push(0);
		ans.push_back(-1);
		for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
		{
			while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
			if (st.empty())ans.push_back(-1);
			else ans.push_back(st.top());
			st.push(i);
		}
		return ans;
	}

	//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
	template
	static vector fminlef(vector v)
	{
		return firstInLeft(v, [](T a, T b) {return a < b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
	template
	static vector fminlef2(vector v)
	{
		return firstInLeft(v, [](T a, T b) {return a <= b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
	template
	static vector fmaxlef(vector v)
	{
		fcheng(v, -1);
		vectorans = fminlef(v);
		return ans;
	}
	//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
	template
	static vector fmaxlef2(vector v)
	{
		fcheng(v, -1);
		vectorans = fminlef2(v);
		return ans;
	}

	//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
	template
	static vector fminrig(vector v)
	{
		vectorv1 = frev(v), v2 = fminlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
	template
	static vector fminrig2(vector v)
	{
		vectorv1 = frev(v), v2 = fminlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
	template
	static vector fmaxrig(vector v)
	{
		vectorv1 = frev(v), v2 = fmaxlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
	template
	static vector fmaxrig2(vector v)
	{
		vectorv1 = frev(v), v2 = fmaxlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
};

class VectorJoin :public Basic
{
public:

	//把v分成前面k个和后面的v.size()-k个,返回拆出来的后面的数组,v本身只留k个
	template
	static vector vecSplit(vector& v, int k)
	{
		vectorv2;
		v2.resize(v.size() - k);
		copy(v.begin() + k, v.end(), v2.begin());
		v.resize(k);
		return v2;
	}
	//把{1,2,3,4,5,6,7}循环拆分成{1,4,7}{2,5}{3,6}
	template
	static vector> loopSplit(vector& v, int num)
	{
		vector>v2(num);
		for (int i = 0; i < v.size(); i++)v2[i % num].push_back(v[i]);
		return v2;
	}
	//交叉交换,v1分成前面k1个和后面的v1.size()-k1个,v2同理,交换后面的2段
	template
	static void crossChange(vector& v1, vector& v2, int k1, int k2)
	{
		vectorv3 = vecSplit(v1, k1), v4 = vecSplit(v2, k2);
		v1 = join(v1, v4), v2 = join(v2, v3);
	}
	//vector的择优合并
	template
	static vector mergeVector(const vector& a, const vector& b)
	{
		vector ans;
		int i;
		for (i = 0; i < a.size() && i < b.size(); i++) {
			if (isGreater(a[i], b[i]))ans.push_back(a[i]);
			else ans.push_back(b[i]);
		}
		for (; i < a.size(); i++)ans.push_back(a[i]);
		for (; i < b.size(); i++)ans.push_back(b[i]);
		return ans;
	}
	//二维vector拼接转化成一维的
	template
	static vector foldJoin(const vector>& v)
	{
		vectorans;
		for (auto& vi : v)ans = join(ans, vi);
		return ans;
	}
	//把vector自复制一份,前后拼接起来
	template
	static vector selfCopyJoin(const vector& v)
	{
		return join(v, v);
	}
private:
	template
	static bool isGreater(T a, T b)
	{
		return a > b;
	}
};

class VectorOpt
{
public:
	//收缩计数,把[1 4 4 1]变成canSort ? [(1,2)(4,2)] : [(1,1)(4,2)(1,1)]
	template
	static vector> fshr(vectorv, bool canSort = true) //谨慎传引用
	{
		vector>ans;
		if (v.size() == 0)return ans;
		if (canSort)sort(v.begin(), v.end());
		int low = 0;
		for (int i = 1; i <= v.size(); i++) {
			if (i == v.size() || v[i] != v[i - 1]) {
				ans.push_back(make_pair(v[i - 1], i - low));
				low = i;
			}
		}
		return ans;
	}
	//平摊,把 [(1,2)(4,2)]变成[1 1 4 4]
	template
	static vector funshr(vector>& v)
	{
		vectorans;
		for (auto p : v) {
			for (int i = 0; i < p.second; i++)ans.push_back(p.first);
		}
		return ans;
	}
	//生成枚举序号
	template
	static vector> foreach(const vector>& v)
	{
		int s = 1;
		for (auto& vi : v)s *= vi.size();
		vector> ans;
		while (s--)
		{
			vector vt;
			int st = s;
			for (int j = v.size() - 1; j >= 0; j--)
			{
				vt.insert(vt.begin(), st % v[j].size());
				st /= v[j].size();
			}
			ans.push_back(vt);
		}
		return ans;
	}
	//根据各数字对应的替换列表,生成各种替代枚举
	template
	static vector> changeMeiJu(const vector& data, map>options)
	{
		vector> ans(1, data);
		int len = data.size();
		for (int i = 0; i < len; i++) {
			int s = ans.size();
			for (int j = 0; j < s; j++)for (auto op : options[data[i]]) {
				vector x = ans[j];
				x[i] = op;
				ans.push_back(x);
			}
		}
		return ans;
	}
	//根据各id对应的替换列表,生成各种替代枚举
	template
	static vector subMeiJu(const T &data, int len, mapoptions)
	{
		vector ans;
		ans.push_back(data);
		for (int i = 0; i < len; i++) {
			int s = ans.size();
			for (int j = 0; j < s; j++)for (auto op : options[i]) {
				T x = ans[j];
				x[i] = op;
				ans.push_back(x);
			}
		}
		return ans;
	}
	//拓展数据域,加上id
	template
	static inline vector>expand(const vector& v)
	{
		vector>ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i].first = v[i], ans[i].second = i;
		return ans;
	}
	//给vector拓展,加上id并拓展成稳定排序
	template
	static inline vector> sortWithId(const vector& v)
	{
		vector>ans = expand(v);
		sort(ans.begin(), ans.end(), cmpPair);
		return ans;
	}
    //给vector拓展,加上id,但只按照原数据进行排序
	template
	static inline vector> sortWithOrderMatch(const vector& v)
	{
		vector>ans = expand(v);
		sort(ans.begin(), ans.end(), cmpJustFirst);
		return ans;
	}
	//排序后数组中的每个数的原ID,输入8 5 6 7,输出1 2 3 0,也可以直接求逆置换
	template
	static inline vector sortId(const vector& v)
	{
		auto vp = sortWithId(v);
		vectorans;
		transform(vp.begin(), vp.end(), back_inserter(ans), [](const pair& p) {return p.second; });
		return ans;
	}
	//每个数在排序后的数组中的ID,输入8 5 6 7,输出3 0 1 2
	template
	static inline vector sortId2(const vector& v)
	{
		return sortId(sortId(v));
	}
	//给v排序,v2按照同样的顺序调整,输入{1,3,2}{4,5,6},输出{1,2,3}{4,6,5}
	template
	static inline void sortExtend(vector& v, vector& v2)
	{
		auto ids = sortId(v);
		auto v3 = v, v4 = v2;
		for (int i = 0; i < v.size(); i++)v[i] = v3[ids[i]], v2[i] = v4[ids[i]];
	}
	//2个vector中寻找和为s的对,返回结果的每一行都是[id1,id2]
	template
	static vector> findSum(vectorv1, vectorv2, T s)
	{
		vector>ans;
		int m = min((long long)(v1.size() * v2.size()), (long long)12345678);
		ans.reserve(m);
		vectortmp(2);
		vectorv3 = sortId(v2);
		sort(v2.begin(), v2.end(), cmp);
		for (int i = 0; i < v1.size(); i++)
		{
			auto it1 = lower_bound(v2.begin(), v2.end(), s - v1[i]);
			auto it2 = upper_bound(v2.begin(), v2.end(), s - v1[i]);
			tmp[0] = i;
			for (auto j = it1; j < it2; j++)
			{
				tmp[1] = v3[j - v2.begin()];
				ans.push_back(tmp);
			}
		}
		return ans;
	}
	//vector的字典序比较,v1=v2是false
	template
	static bool cmpVector(const vector& v1, const vector& v2)
	{
		for (int i = 0; i < v1.size() && i < v2.size(); i++)
		{
			if (v1[i] != v2[i])return v1[i] < v2[i];
		}
		return v1.size() < v2.size();
	}
	//vector的字典序排序
	template
	static void sortVector(vector>& v)
	{
		sort(v.begin(), v.end(), cmpVector);
	}
private:
	template
	static inline bool cmp(T a, T b)
	{
		return a < b;
	}
	static inline bool cmp(string a, string b)
	{
		return a.length() < b.length();
	}
	template
	static inline bool cmpPair(pair x, pair y)
	{
		if (cmp(x.first, y.first))return true;
		if (cmp(y.first, x.first))return false;
		return cmp(x.second, y.second);
	}
	template
	static inline bool cmpJustFirst(pair x, pair y)
	{
		return cmp(x.first, y.first);
	}
};
class VectorCal
{
public:
	//2个vector相加
	template
	static vector vecAdd(const vector& v1, const vector& v2)
	{
		vectorv(max(v1.size(), v2.size()));
		for (int i = 0; i < v.size(); i++)v[i] = 0;
		for (int i = 0; i < v1.size(); i++)v[i] += v1[i];
		for (int i = 0; i < v2.size(); i++)v[i] += v2[i];
		return v;
	}
	//枚举2个vector的两数之和
	template
	static vector everySum(vector& v1, vector& v2)
	{
		vectorans;
		ans.resize(v1.size() * v2.size());
		int k = 0;
		for (int i = 0; i < v1.size(); i++)for (int j = 0; j < v2.size(); j++)ans[k++] = v1[i] + v2[j];
		return ans;
	}
	//判断2个vector(一维或二维)是否全等
	template
	static bool isSame(const vector& v1, const vector& v2)
	{
		if (v1.size() - v2.size())return false;
		for (int i = 0; i < v1.size(); i++)if (v1[i] != v2[i])return false;
		return true;
	}
	template
	static bool isSame(const vector>& v1, const vector>& v2) {
		if (v1.size() - v2.size())return false;
		for (int i = 0; i < v1.size(); i++)if (!isSame(v1[i], v2[i]))return false;
		return true;
	}
	//二维数组去掉重复行
	template
	static vector> deleteSameLine(const vector>& v)
	{
		vector>ans;
		ans.reserve(v.size());
		for (int i = 0; i < v.size(); i++)
		{
			bool flag = true;
			for (int j = i + 1; flag && j < v.size(); j++)if (isSame(v[i], v[j]))flag = false;
			if (flag)ans.push_back(v[i]);
		}
		return ans;
	}
	//判断vector中是否含有重复元素
	template
	static bool haveSameData(vector v)// not const
	{
		sort(v.begin(), v.end());
		for (int i = 1; i < v.size(); i++)if (v[i] == v[i - 1])return true;
		return false;
	}
	//删除二维vector中,含有重复元素的行
	template
	static vector> deleteLineWithSameDatas(vector>& v)
	{
		vector>ans;
		ans.reserve(v.size());
		for (int i = 0; i < v.size(); i++)
		{
			if (!haveSameData(v[i]))ans.push_back(v[i]);
		}
		return ans;
	}
	//2个vector的卷积
	template
	static vector vecConvolution(vector& v1, vector& v2)
	{
		vectorans(v1.size() + v2.size() - 1);
		for (int i = 0; i < v1.size(); i++)for (int j = 0; j < v2.size(); j++)ans[i + j] += v1[i] * v2[j];
		return ans;
	}
};

三,链表


#ifdef LOCAL
struct listtNode {
	int val;
	listtNode* next;
	listtNode(int x) : val(x), next(NULL) {}
};
#define ListNode listtNode
#endif
class LinkList
{
public:
	//构建链表
	static ListNode* initLinkList(const vector& v)
	{
		ListNode* head = new ListNode(0);
		ListNode* tail = head;
		for (auto vi : v)tail = tail->next = new ListNode(vi);
		return head->next;
	}
	//打印链表
	static void outLinkList(ListNode* head)
	{
		while (head) {
			cout << head->val << " ";
			head = head->next;
		}
	}
	//获取链表长度
	static int getLength(ListNode* p)
	{
		int ans = 0;
		while (p)
		{
			ans++;
			p = p->next;
		}
		return ans;
	}
    //两个链表的数据是否全等
	static bool isSameLinkList(ListNode*p1, ListNode*p2)
	{
		if (!p1 && !p2)return true;
		return p1 && p2 && p1->val == p2->val && isSameLinkList(p1->next, p2->next);
	}
	//链表反转,返回新的head
	static ListNode* reverse(ListNode* p)
	{
		if (p == NULL)return p;
		ListNode* q1;
		ListNode* q2;
		q1 = p->next, p->next = NULL;
		while (q1)
		{
			q2 = q1->next, q1->next = p, p = q1, q1 = q2;
		}
		return p;
	}
	//链表中倒数第k个节点
	static ListNode* getKthFromEnd(ListNode* head, int k) {
		ListNode* p = head;
		while (p && k--)p = p->next;
		while (p)p = p->next, head = head->next;
		return head;
	}
	//链表最后一个节点
	static ListNode* getTail(ListNode* head)
	{
		return getKthFromEnd(head,1);
	}
	//留下前k个节点,把后面的切下来并返回
	static ListNode* linkSplit(ListNode* head, int k)
	{
		while (--k && head) {
			head = head->next;
		}
		if (!head)return head;
		auto ans = head->next;
		head->next = nullptr;
		return ans;
	}
	//直接合并2个链表
	static void linkMerge(ListNode* p1, ListNode* p2)
	{
		getTail(p1)->next = p2;
	}
	//把两个链表交叉合并为一个链表
	static ListNode* mergeTwoLists(ListNode* p, ListNode* q) {
		if (!p)return q;
		if (!q)return p;
		ListNode* pnext, * qnext, * ans = p;
		while (p && q)
		{
			if (p->next == NULL && q->next != NULL)
			{
				p->next = q;
				break;
			}
			pnext = p->next, qnext = q->next;
			p->next = q, q->next = pnext;
			p = pnext, q = qnext;
		}
		return ans;
	}
	//把两个升序的链表合并为一个升序的链表
	static ListNode* mergeTwoUpLists(ListNode* p, ListNode* q) {
		if (!p)return q;
		if (!q)return p;
		ListNode* head;
		if (p->val < q->val)head = p, p = p->next;
		else head = q, q = q->next;
		ListNode* ans = head;
		while (p && q)
		{
			if (p->val < q->val)ans->next = p, ans = p, p = p->next;
			else ans->next = q, ans = q, q = q->next;
		}
		if (p)ans->next = p;
		else ans->next = q;
		return head;
	}
	//把链表转化成结构体指针数组
	static vector listToVec(ListNode* head)
	{
		vectorans;
		while (head)
		{
			ans.push_back(head);
			head = head->next;
		}
		return ans;
	}
	//把结构体指针数组转化成链表
	static ListNode* vecToList(vectorv)
	{
		if (v.empty())return NULL;
		for (int i = 0; i < v.size() - 1; i++)v[i]->next = v[i + 1];
		v[v.size() - 1]->next = NULL;
		return v[0];
	}
	//链表排序
	static ListNode* sortLinkList(ListNode* head)
	{
		vectorv = listToVec(head);
		sort(v.begin(), v.end(), cmp);
		return vecToList(v);
	}
	//判断链表是否有环,有环返回环中任意节点,没环返回NULL
	static ListNode* getAnyoneInCycle(ListNode* head) {
		if (!head)return NULL;
		ListNode* p1 = head, * p2 = head->next;
		while (p1 != p2)
		{
			if (!p1)return NULL;
			p1 = p1->next;
			if (!p2)return NULL;
			p2 = p2->next;
			if (!p2)return NULL;
			p2 = p2->next;
		}
		return p1;
	}
	//求链表环的长度,没环返回0
	static int getCycleLen(ListNode* head) {
		ListNode* p = getAnyoneInCycle(head);
		if (!p)return 0;
		ListNode* q = p->next;
		int ans = 1;
		while (q != p)q = q->next, ans++;
		return ans;
	}
	//求链表环的第一个节点,没环返回NULL
	static ListNode* getFirstInCycle(ListNode* head) {
		int len = getCycleLen(head);
		if (len == 0)return NULL;
		ListNode* p = head;
		while (len--)p = p->next;
		while (head != p)head = head->next, p = p->next;
		return p;
	}
private:
	static bool cmp(ListNode*& a, ListNode*& b)
	{
		return a->val < b->val;
	}
};
struct DeListNode {
	int val;
	DeListNode* left;
	DeListNode* right;
	DeListNode() {}
	DeListNode(int _val) {
		val = _val;
		left = NULL;
		right = NULL;
	}
	DeListNode(int _val, DeListNode* _left, DeListNode* _right) {
		val = _val;
		left = _left;
		right = _right;
	}
};
class DeLinkList
{
public:
	//创建单节点双向循环链表
	static DeListNode* getSingleDeList(int val = 0)
	{
		DeListNode* p = new DeListNode();
		p->left = p, p->right = p, p->val = val;
		return p;
	}
	//合并双向循环链表
	static void mergeDelist(DeListNode* p1, DeListNode* p2)
	{
		if (!p1 || !p2)return;
		p1->left->right = p2, p2->left->right = p1;
		DeListNode* tmp = p2->left;
		p2->left = p1->left;
		p1->left = tmp;
	}
    //获取链表长度
	static int getLengthOfDeLL(DeListNode* p)
	{
		int ans = 1;
		auto head = p;
		p = p->right;
		while (p != head)
		{
			ans++;
			p = p->right;
		}
		return ans;
	}
};

四,STL操作封装、拓展数据结构、背包


class StlBasicOpt
{
public:
	//获取列表某处的值
	template
	static T vecGet(const vector& v, int id)
	{
		return (id >= 0 && id < v.size()) ? v[id] : T{};
	}
	//id处覆盖或者添加一个数
	template
	static void finsert(vector& v, int id, T x)
	{
		if (id<0 || id>v.size())return;
		if (id == v.size())v.push_back(x);
		v[id] = x;
	}
	//multi***容器x删除一个数值n
	template
	static void delOnlyOne(T& x, T2 n)
	{
		auto it = x.find(n);
		if (it != x.end())x.erase(it);
	}
	//删除最后一个元素
	template
	static void delEnd(T &x)
	{
		x.erase(--(x.end()));
	}
};

//单调栈
class MonotonicStack {
public:
	MonotonicStack(int type, bool force) { //0递减栈,栈顶最小,1递增栈,栈顶最大, force表示是否是强制单调栈
		this->type = type, this ->force = force;
	}
	void push(int x) {
		if (force) {
			while (!s.empty() && (type ? (s.top() > x) : (s.top() < x)))s.pop();
			s.push(x);
		}
		else {
			if (s.empty() || (type ? (s.top() <= x) : (s.top() >= x)))s.push(x);
		}
	}
	void pop() {
		if (!s.empty())s.pop();
	}
	int top() {
		return s.top();
	}
	int size() {
		return s.size();
	}
private:
	stacks;
	int type;
	bool force;
};
//栈的拓展,支持获取最值,所有接口时间复杂度都是 O(1)
class MinMaxStack {
public:
	MinMaxStack(int type) { //0最小栈 1最大栈
		this->type = type;
	}
	void push(int x) {//入栈
		s.push(x);
		if (m.empty() || (type ? (m.top() <= x) : (m.top() >= x)))m.push(x);
	}
	void pop() {//出栈
		if (m.top() == s.top())m.pop();
		s.pop();
	}
	int top() {//获取栈顶
		return s.top();
	}
	int minMax() {//获取最值
		return m.top();
	}
private:
	stacks;//主栈
	stackm;//单调栈
	int type;
};
//栈的拓展,支持删除最值,所有接口时间复杂度都在 O(log n)之内
class MinMaxStack2 : public StlBasicOpt
{
public:
	MinMaxStack2(int type) {//0最小栈 1最大栈
		this->type = type;
	}
	int peekMinMax() { //获取最值
		while (m.rbegin()->second.empty())delEnd(m);
		return m.rbegin()->first;
	}
	int popMinMax() { //获取最值并删除
		int t = peekMinMax();
		m2[t].insert(*(m[t].rbegin()));
		delEnd(m[t]);
		return t;
	}
	void push(int t) {
		v.push_back(t);
		int num = 0;
		if (!m[t].empty())num = max(num, *(m[t].rbegin()));
		if (!m2[t].empty())num = max(num, *(m2[t].rbegin()));
		m[t].insert(num + 1);
	}
	int pop() {
		int t = top();
		delEnd(m[t]);
		delEnd(v);
		return t;
	}
	int top() {
		while (true) {
			int t = v.back();
			if (m2[t].empty())break;
			if (!m[t].empty()) {
				if (type ? (*(m[t].rbegin()) > *(m2[t].rbegin())) : (*(m[t].rbegin()) < *(m2[t].rbegin())))break;
			}
			delEnd(m2[t]);
			delEnd(v);
		}
		return v.back();
	}
private:
	map>m;//现存列表
	map>m2;//删除列表
	vectorv;
	int type;
};

//单调队列
class MonotonicQueue {
public:
	MonotonicQueue(int type) { //0递增队列,队首最小,1递减队列,队首最大
		this->type = type;
		id = 0;
	}
	void push_back(int x) {
		while (!q.empty() && (type ? (m[q.back()] < x) : (m[q.back()] > x)))q.pop_back();
		q.push_back(id);
		m[id++] = x;
	}
	void pop_front() {
		if (!q.empty())q.pop_front();
	}
	void pop_back() {
		if (!q.empty())q.pop_back();
	}
	int frontId() {
		return q.front();
	}
	int front() {
		return m[q.front()];
	}
	int tailId() {
		return q.back();
	}
	int size() {
		return q.size();
	}
private:
	dequeq;
	mapm;
	int type, id;
};
//队列的拓展,支持获取最值,所有接口的均摊时间复杂度都是O(1)
class MinMaxQueue : public StlBasicOpt
{
public:
	MinMaxQueue(int type) { //0最小队列 1最大队列
		this->type = type, vlen = 0;
	}
	int max_value() {
		if (q.empty())return error;
		return v[0];
	}
	void push_back(int value) {
		q.push(value);
		bool flag = true;
		for (int i = vlen; flag && i > 0; i--)
		{
			if (type ? (value <= v[i - 1]) : (value >= v[i - 1]))
			{
				finsert(v, i, value);
				vlen = i + 1;
				flag = false;
			}
		}
		if (flag)
		{
			finsert(v, 0, value);
			vlen = 1;
		}
	}
	int pop_front() {
		if (q.empty())return error;
		int ans = q.front();
		q.pop();
		if (v[0] == ans)
		{
			v.erase(v.begin());
			vlen--;
		}
		return ans;
	}
private:
	queueq;
	vectorv;
	int type;
	int vlen;
	int error = -1;
};
template
class QueueWithNoSameData //不含重复元素的队列
{
public:
	void push(T x) {
		if (m[x] == 0)q.push(x), m[x] = 1;
	}
	void pop() {
		m[q.front()] = 0;
		q.pop();
	}
	T front() {
		return q.front();
	}
	bool empty() {
		return q.empty();
	}
private:
	queueq;
	mapm;
};
//01背包、完全背包、多重背包、混合背包
class Pack {
public:
	//01背包,输入总体积,每个物品的体积和得分,输出最高总得分
	static int pack01(int v, const vector& volume, const vector& score) {
		vectorans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++)pack01Opt(v, volume[i], score[i], ans);
		return ans[v];
	}
	//0-1增强代价背包,需要有volumePlus大小的空间,才能放入volume大小的物品,输出最高总得分
	static int packPlus(int v, const vector& volumePlus, const vector& volume, const vector& score) {
		vectorvec = transPackPlusToNodes(volumePlus, volume, score);
		vectorans(v + 1, 0);
		for (int i = 0; i < vec.size(); i++) {
			for (int j = v; j >= vec[i].vp; j--) {
				ans[j] = max(ans[j], ans[j - vec[i].v] + vec[i].s);
			}
		}
		return ans[v];
	}
	//0-1双得分背包,每个物品有2个得分,输出score的最高总得分,以及在该得分前提下,score2的最高总得分,score2可以为负
	static vector packDoubleScore(int v, const vector& volume, const vector& score, const vector& score2) {
		vectorans(v + 1, 0), ans2(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= volume[i]; j--) {
				int j2 = j - volume[i];
				if (ans[j] < ans[j2] + score[i])ans[j] = ans[j2] + score[i], ans2[j] = ans2[j2] + score2[i];
				else if (ans[j] == ans[j2] + score[i] && ans2[j] < ans2[j2] + score2[i])ans2[j] = ans2[j2] + score2[i];
			}
		}
		return vector{ans[v], ans2[v]};
	}
	//01背包组合计数,输入总体积,每个物品的体积,输出刚好塞满的方案数,不区分顺序
	static int pack01Num(int v, const vector& volume) {
		vectorans(v + 1, 0);
		ans[0] = 1;
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= volume[i]; j--) {
				ans[j] += ans[j - volume[i]];
			}
		}
		return ans[v];
	}
	//完全背包,输入总体积,每个物品的体积和得分,输出最高总得分
	static int packComplete(int v, const vector& volume, const vector& score) {
		vectorans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++)pack01Opt(v, volume[i], score[i], ans);
		return ans[v];
	}
	//完全增强代价背包,需要有volumePlus大小的空间,才能放入volume大小的物品,输出最高总得分
	static int packCompletePlus(int v, const vector& volumePlus, const vector& volume, const vector& score) {
		vectorvec = transPackPlusToNodes(volumePlus, volume, score);
		vectorans(v + 1, 0);
		for (int i = 0; i < vec.size(); i++) {
			for (int j = vec[i].vp; j <= v; j++) {
				ans[j] = max(ans[j], ans[j - vec[i].v] + vec[i].s);
			}
		}
		return ans[v];
	}
	//完全双得分背包,每个物品有2个得分,输出score的最高总得分,以及在该得分前提下,score2的最高总得分,score2可以为负
	static vector packCompleteDoubleScore(int v, const vector& volume, const vector& score, const vector& score2) {
		vectorans(v + 1, 0), ans2(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = volume[i]; j <= v; j++) {
				int j2 = j - volume[i];
				if (ans[j] < ans[j2] + score[i])ans[j] = ans[j2] + score[i], ans2[j] = ans2[j2] + score2[i];
				else if (ans[j] == ans[j2] + score[i] && ans2[j] < ans2[j2] + score2[i])ans2[j] = ans2[j2] + score2[i];
			}
		}
		return vector{ans[v], ans2[v]};
	}
	//完全背包组合计数,输入总体积,每个物品的体积,输出刚好塞满的方案数,不区分顺序
	static int packCompleteNum(int v, const vector& volume) {
		vectorans(v + 1, 0);
		ans[0] = 1;
		for (int i = 0; i < volume.size(); i++) {
			for (int j = volume[i]; j <= v; j++) {
				ans[j] += ans[j - volume[i]];
			}
		}
		return ans[v];
	}
	//完全背包排列计数,输入总体积,每个物品的体积,输出刚好塞满的方案数,区分顺序
	static long long packCompleteNumA(int v, const vector& volume, long long p = UINT_MAX) {
		vectorans(v + 1, 0);
		ans[0] = 1;
		for (int j = 0; j <= v; j++) {
			for (int i = 0; i < volume.size(); i++) {
				if (j >= volume[i])ans[j] = (ans[j] + ans[j - volume[i]]) % p;
			}
		}
		return ans[v];
	}
	//多重背包,输入总体积,每个物品的体积和数量和得分,输出最高总得分
	static int packMulti(int v, const vector& volume, const vector& num, const vector& score) {
		vectorans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++)packMultiOpt(v, volume[i], num[i], score[i], ans);
		return ans[v];
	}
	//01、完全、多重的混合背包,num=1是01背包,num=-1是完全背包,num>1是多重背包
	static int packMix(int v, const vector& volume, const vector& num, const vector& score) {
		vectorans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			if (num[i] == 1)pack01Opt(v, volume[i], score[i], ans);
			if (num[i] == -1)packCompleteOpt(v, volume[i], score[i], ans);
			if (num[i] > 1)packMultiOpt(v, volume[i], num[i], score[i], ans);
		}
		return ans[v];
	}
private:
	struct node
	{
		int vp, v, s;
		static bool cmp(node a, node b)
		{
			return a.vp - a.v < b.vp - b.v;
		}
	};
	static vector transPackPlusToNodes(const vector& volumePlus, const vector& volume, const vector& score)
	{
		vectorvec;
		for (int i = 0; i < volumePlus.size(); i++) {
			vec.push_back({ volumePlus[i],volume[i],score[i] });
		}
		sort(vec.begin(), vec.end(), node::cmp);
		return vec;
	}
	static inline void pack01Opt(int v, int volumei, int scorei, vector&ans) {
		for (int j = v; j >= volumei; j--) {
			ans[j] = max(ans[j], ans[j - volumei] + scorei);
		}
	}
	static inline void packCompleteOpt(int v, int volumei, int scorei, vector&ans) {
		for (int j = volumei; j <= v; j++) {
			ans[j] = max(ans[j], ans[j - volumei] + scorei);
		}
	}
	static inline void packMultiOpt(int v, int volumei, int numi, int scorei, vector&ans) {
		for (int j = 0; j < volumei; j++) {
			MonotonicQueue q(1);
			for (int k = j; k <= v; k += volumei) {
				q.push_back(ans[k] - k / volumei * scorei);
				ans[k] = k / volumei * scorei + q.front();
				if (q.tailId() - numi == q.frontId())q.pop_front();
			}
		}
	}
};
//双代价背包
class PackDoubleVolume {
public:
	//0-1双代价背包,每个物品有2个代价,输出最高总得分
	static int pack01(int v, int v2, const vector& volume, const vector& volume2, const vector& score) {
		vector>ans(v + 1, vector(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++)pack01Opt(v, v2, volume[i], volume2[i], score[i], ans);
		return ans[v][v2];
	}
	//增强双代价背包,每个物品有2个代价,输出最高总得分
	static int packComplete(int v, int v2, const vector& volume, const vector& volume2, const vector& score) {
		vector>ans(v + 1, vector(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++)packCompleteOpt(v, v2, volume[i], volume2[i], score[i], ans);
		return ans[v][v2];
	}
	//多重双代价背包,每个物品有2个代价,输出最高总得分
	static int packMulti(int v, int v2, const vector& volume, const vector& volume2, const vector& num, const vector& score) {
		vector>ans(v + 1, vector(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++) packMultiOpt(v, v2, volume[i], volume2[i], num[i], score[i], ans);
		return ans[v][v2];
	}
	//01、完全、多重的混合背包,num=1是01背包,num=-1是完全背包,num>1是多重背包
	static int packMix(int v, int v2, const vector& volume, const vector& volume2, const vector& num, const vector& score) {
		vector>ans(v + 1, vector(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++) {
			if (num[i] == 1)pack01Opt(v, v2, volume[i], volume2[i], score[i], ans);
			if (num[i] == -1)packCompleteOpt(v, v2, volume[i], volume2[i], score[i], ans);
			if (num[i] > 1)packMultiOpt(v, v2, volume[i], volume2[i], num[i], score[i], ans);
		}
		return ans[v][v2];
	}
private:
	static inline void pack01Opt(int v, int v2, int volumei, int volume2i, int scorei, vector>&ans) {
		for (int j = v; j >= volumei; j--) {
			for (int j2 = v2; j2 >= volume2i; j2--) {
				ans[j][j2] = max(ans[j][j2], ans[j - volumei][j2 - volume2i] + scorei);
			}
		}
	}
	static inline void packCompleteOpt(int v,int v2, int volumei,int volume2i, int scorei, vector>&ans) {
		for (int j = volumei; j <= v; j++) {
			for (int j2 = volume2i; j2 <= v2; j2++) {
				ans[j][j2] = max(ans[j][j2], ans[j - volumei][j2 - volume2i] + scorei);
			}
		}
	}
	static inline void packMultiOpt(int v, int v2, int volumei, int volume2i, int numi, int scorei, vector>&ans) {
		for (int j = 0; j <= v; j++) {
			for (int j2 = 0; j2 <= (j < volumei ? v2 : volume2i - 1); j2++) {
				MonotonicQueue q(1);
				for (int k = j, k2 = j2; k <= v, k2 <= v2; k += volumei, k2 += volume2i) {
					q.push_back(ans[k][k2] - k / volumei * scorei);
					ans[k][k2] = k / volumei * scorei + q.front();
					if (k / volumei - numi == q.frontId())q.pop_front();
				}
			}
		}
	}
};
//分组背包
class PackGroup {
public:
	//分组背包,输入总体积,每组每个物品的体积和得分,输出最高总得分
	static int packGroup01(int v, const vector>& volume, const vector>& score) {
		return packGroup01Ans(v, volume, score)[v];
	}
	//分组背包组合计数,输入总体积,每组每个物品的体积,输出刚好塞满的方案数,不区分顺序
	static int packGroup01Num(int v, const vector>& volume) {
		vectorans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= 0; j--) {
				for (int k = 0; k < volume[i].size(); k++) {
					if (j >= volume[i][k])ans[j] += ans[j - volume[i][k]];
				}
			}
		}
		return ans[v];
	}
protected:
	//分组背包,输入总体积,每组每个物品的体积和得分,输出最高总得分
	static vector packGroup01Ans(int v, const vector>& volume, const vector>& score) {
		vectorans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= 0; j--) {
				for (int k = 0; k < volume[i].size(); k++) {
					if (j >= volume[i][k])ans[j] = max(ans[j], ans[j - volume[i][k]] + score[i][k]);
				}
			}
		}
		return ans;
	}
};
//泛化物品背包
class PackGeneralize :public PackGroup {
public:
	//每个物品的价值函数score[i]都是一个长为v+1的数组
	static int pack01(int v, const vector>& score) {
		return pack01Ans(v, score)[v];
	}
protected:
	static vector pack01Ans(int v, const vector>& score) {
		vector> volume2, score2;
		for (auto &s : score) {
			vectorvi, si;
			for (int i = 1; i <= v; i++) {
				vi.push_back(i), si.push_back(s[i]);
			}
			volume2.push_back(vi), score2.push_back(si);
		}
		return packGroup01Ans(v, volume2, score2);
	}
};
//依赖背包(仅限森林)
class PackDepend:public PackGeneralize {
public:
	//依赖背包(仅限森林),children是每个节点的子节点集,所有节点编号0到n-1,children和volume和score的长度都为n
	static int packDependTrees(int v,const vector>&children, const vector& volume, const vector& score) {
		return packDependTrees(v, getRoots(children), children, volume, score)[v];
	}
	//依赖背包(仅限森林),fas是所有根节点,children是每个节点的子节点集,所有节点编号0到n-1,children和volume和score的长度都为n
	static vector packDependTrees(int v, const vector &roots, const vector>&children, const vector& volume, const vector& score) {
		vector> score2;
		for (auto root : roots) {
			score2.push_back(packDependTree(v, root, children, volume, score));
		}
		return PackGeneralize::pack01Ans(v, score2);
	}
private:
	static vector getRoots(const vector>&children) {
		mapm;
		for (auto &cs : children)for (auto x : cs)m[x]++;
		vectorroots;
		for (int i = 0; i < children.size(); i++)if (m[i] == 0)roots.push_back(i);
		return roots;
	}
	static vector packDependTree(int v, int root, const vector>&children, const vector& volume, const vector& score) {
		vector ans(v+1,0);
		if (volume[root] > v)return ans;
		if (children[root].empty()) {
			ans[volume[root]] = score[root];
			return ans;
		}
		return packDependTrees(v - volume[root], children[root], children, volume, score);
	}
};

五,test

#define EXPECT_VEC_EQ(a,b) if(!IsSame((a),(b))){cout<<"ERROR!!!!!!!!!\n";return false;}
#define EXPECT_EQ(a,b) if(a!=b){cout<<"ERROR!!!!!!!!!\n";return false;}
#define EXPECT_LINK_EQ(a,b) if(!IsSameLinkList((a),(b))){cout<<"ERROR!!!!!!!!!\n";return false;}

bool test1()
{
	vectorv;
	// Read(v); // 输入3 100 200 300
	// Print(v); // 输出"v =  size = 3 \n  100 200 300"
	return true;
}

bool testBasic()
{
	vectorv1{ 1,2,3 };
	vectorv2{ 3,5 };
	vectorv3 = FvecJoin(v1, v2);
	EXPECT_VEC_EQ(v3, (vector{1, 2, 3, 3, 5}));
	vectorv4{ 3,6 };
	EXPECT_VEC_EQ(Frev(v4), (vector{6, 3}));
	return true;
}
bool testSingleVectorOpt()
{
	vector> v{ {'a','b'},{'c','0'} };
	EXPECT_VEC_EQ(FoldJoin(v), (vector{ 'a', 'b', 'c', '0' }));
	EXPECT_VEC_EQ(FoldJoin(Foverturn(v)), (vector{ 'a', 'c', 'b', '0' }));
	EXPECT_VEC_EQ(FoldJoin(Frotation(v)), (vector{ 'c', 'a', '0', 'b' }));
	Delet(v, '0');
	EXPECT_VEC_EQ(FoldJoin(v), (vector{ 'a', 'b', 'c'}));
	vectorv2{ 1,2,2,3,4,5,5,6 };
	EXPECT_EQ(GetDifNum(v2), 6);
	Fcheng(v2, 2);
	Fjia(v2, 1);
	EXPECT_VEC_EQ(v2, (vector{3, 5, 5, 7, 9, 11, 11, 13}));
	v[1].push_back('a');
	EXPECT_VEC_EQ(FoldJoin(v), (vector{ 'a', 'b', 'c', 'a'}));
	SortEveryLine(v);
	EXPECT_VEC_EQ(FoldJoin(v), (vector{ 'a', 'b', 'a', 'c'}));
	vectorv3{ 1,3,5,2,4 };
	EXPECT_VEC_EQ(Fminlef(v3), (vector{-1, 0, 1, 0, 3}));
	return true;
}
bool testVectorJoin()
{
	vectorv{ 2,2,4,7 }, v2{ 3,1,3,5 };
	auto v3 = VecSplit(v, 3);
	EXPECT_VEC_EQ(v, (vector{2, 2, 4}));
	EXPECT_VEC_EQ(v3, (vector{7}));
	v3 = MergeVector(v, v2);
	EXPECT_VEC_EQ(v3, (vector{3, 2, 4, 5})); //{2, 2, 4}和{ 3,1,3,5 }  -> {3, 2, 4, 5}
	v3 = SelfCopyJoin(v3);
	EXPECT_VEC_EQ(v3, (vector{3, 2, 4, 5, 3, 2, 4, 5}));
	auto v4 = LoopSplit(v3, 3);
	EXPECT_VEC_EQ(v4, (vector>{ vector{3, 5, 4}, vector{ 2, 3, 5 }, vector{ 4, 2 }}));
	CrossChange(v2, v3, 2, 3);
	EXPECT_VEC_EQ(v2, (vector{3, 1, 5, 3, 2, 4, 5}));
	EXPECT_VEC_EQ(v3, (vector{3, 2, 4, 3, 5}));
	return true;
}

bool testVectorOpt()
{
	vectorv{ 1,4,4,1 };
	auto vp = Fshr(v, false);
	EXPECT_VEC_EQ(vp, (vector>{make_pair(1, 1), make_pair(4, 2), make_pair(1, 1)}));
	vp = Fshr(v, true);
	EXPECT_VEC_EQ(vp, (vector>{make_pair(1, 2), make_pair(4, 2)}));
	v = Funshr(vp);
	EXPECT_VEC_EQ(v, (vector{ 1, 1, 4, 4}));
	vector> v2{ v,v };
	auto v3 = Foreach(v2);
	EXPECT_EQ(v3.size(), v.size()*v.size());

	v = { 1,2,3 };
	map>options;
	options[1] = { 4 }, options[3] = { 5 };
	auto v4 = ChangeMeiJu(v, options);
	EXPECT_VEC_EQ(v4, (vector> { {1, 2, 3}, { 4,2,3 }, { 1,2,5 }, { 4,2,5 } }));
	map>options2;
	options2[1] = { 6 };
	options2[2] = { 7 };
	v4 = SubMeiJu(v, 3, options2);
	EXPECT_VEC_EQ(v4, (vector> { {1, 2, 3}, { 1,6,3 }, { 1,2,7 }, { 1,6,7 } }));
	v = vector{ 8, 5, 6, 7 };
	EXPECT_VEC_EQ(SortId(v), (vector{1, 2, 3, 0}));
	EXPECT_VEC_EQ(SortId2(v), (vector{3, 0, 1, 2}));
	auto v5 = FindSum(v, v, 13);
	EXPECT_EQ(v5.size(), 4); //85 58 67 76
	EXPECT_EQ(CmpVector(v, vector{ 8, 6, 5, 7 }), true);
	EXPECT_EQ(CmpVector(v, v), false);
	v2 = { {2,3},{1,2} };
	SortVector(v2);
	EXPECT_VEC_EQ(v2, (vector>{ {1, 2}, { 2,3 }}));
	return true;
}

bool testVectorCal()
{
	vectorv1{ 8,5,6,7 }, v2{ 4,5,6,7 };
	EXPECT_VEC_EQ(VecAdd(v1, v2), (vector{12, 10, 12, 14}));
	EXPECT_EQ(EverySum(v1, v2).size(), v1.size() * v2.size());
	vector>v3{ v1,v2,v1 };
	EXPECT_EQ(HaveSameData(v3), true);
	v3 = DeleteSameLine(v3);
	EXPECT_EQ(v3.size(), 2);
	EXPECT_EQ(HaveSameData(v3), false);
	EXPECT_EQ(IsSame(v1, v2), false);
	v2[0] = 8;
	EXPECT_EQ(IsSame(v1, v2), true);
	EXPECT_EQ(VecConvolution(v1, v2).size(), v1.size() + v2.size() - 1);
	return true;
}

bool test2()
{
	return testBasic() && testSingleVectorOpt() && testVectorJoin() && testVectorOpt() && testVectorCal();
}

bool testLinkList()
{
	vectorv{ 1,2,3,4 }, v2{ 4,3,2,1 };
	auto p = InitLinkList(v);
	//OutLinkList(p);
	EXPECT_EQ(GetLength(p), v.size());
	auto p2 = Reverse(InitLinkList(v2));
	EXPECT_LINK_EQ(p, p2);
	auto p3 = GetKthFromEnd(p, 3);
	EXPECT_EQ(p3->val, 2);
	EXPECT_EQ(GetTail(p)->val, 4);

	EXPECT_EQ(GetLength(p), 4);
	p3 = LinkSplit(p, 3); //留下前k个节点,把后面的切下来并返回
	EXPECT_EQ(GetLength(p), 3);
	EXPECT_EQ(GetLength(p3), 1);
	LinkMerge(p, p3);
	EXPECT_LINK_EQ(p, p2);
	p2->val = 5;
	EXPECT_LINK_EQ(MergeTwoLists(p, p2), InitLinkList(vector{1, 5, 2, 2, 3, 3, 4, 4}));
	p = InitLinkList(vector{ 1, 2, 3, 4 });
	p2 = InitLinkList(vector{ 0, 2, 3, 4 });
	EXPECT_LINK_EQ(MergeTwoUpLists(p, p2), InitLinkList(vector{0, 1, 2, 2, 3, 3, 4, 4}));
	return true;
}
bool testDeLinkList()
{
	auto p = GetSingleDeList(1);
	auto p2 = GetSingleDeList(2);
	EXPECT_EQ(GetLengthOfDeLL(p), 1);
	MergeDelist(p, p2);
	EXPECT_EQ(GetLengthOfDeLL(p), 2);
	return true;
}

bool test3()
{
	return testLinkList() && testDeLinkList();
}

bool testStlBasicOpt()
{
	vectorv{ 1, 2, 4, 6 };
	EXPECT_EQ(VecGet(v, 3), 6);
	EXPECT_EQ(VecGet(v, 4), 0);
	Finsert(v, 2, 7);
	EXPECT_VEC_EQ(v, (vector{1, 2, 7, 6}));
	Finsert(v, 4, 7);
	EXPECT_VEC_EQ(v, (vector{1, 2, 7, 6, 7}));
	multisets{ 1, 2, 3, 2, 4 };
	EXPECT_EQ(s.size(), 5);
	DelOnlyOne(s, 2);
	DelEnd(s);
	EXPECT_EQ(s.size(), 3);
	return true;
}

bool testMonotonicStack()
{
	MonotonicStack s(0, true);
	s.push(3); // 3
	s.push(2); // 3 2
	EXPECT_EQ(s.top(), 2);
	EXPECT_EQ(s.size(), 2);
	s.push(4); //先弹出2 再弹出3 再入栈4
	EXPECT_EQ(s.top(), 4);
	EXPECT_EQ(s.size(), 1);
	return true;
}

bool testMinStack()
{
	MinMaxStack s(0);
	s.push(3);
	s.push(1);
	s.push(2);
	EXPECT_EQ(s.top(), 2);
	EXPECT_EQ(s.minMax(), 1);
	s.pop();
	EXPECT_EQ(s.top(), 1);
	return true;
}
bool testMaxStack()
{
	MinMaxStack2 s(1);
	s.push(1);
	s.push(3);
	s.push(2);
	EXPECT_EQ(s.top(), 2);
	EXPECT_EQ(s.peekMinMax(), 3);
	EXPECT_EQ(s.popMinMax(), 3);
	EXPECT_EQ(s.popMinMax(), 2);
	return true;
}
bool testMonotonicQueue()
{
	MonotonicQueue q(0);
	q.push_back(2);
	q.push_back(1);
	q.push_back(3);
	EXPECT_EQ(q.front(), 1);
	return true;
}
bool testMaxQueue()
{
	MinMaxQueue q(1);
	q.push_back(1);
	q.push_back(2);
	q.push_back(1);
	q.push_back(2);
	q.pop_front();
	EXPECT_EQ(q.max_value(), 2);
	return true;
}
bool testQueueWithNoSameData()
{
	QueueWithNoSameDataq;
	q.push(1);
	q.push(2);
	q.push(1);
	EXPECT_EQ(q.front(), 1);
	q.pop();
	EXPECT_EQ(q.front(), 2);
	q.pop();
	EXPECT_EQ(q.empty(), true);
}
bool testPack() // 待完善
{
	//Pack 略。01背包、完全背包、多重背包、混合背包
	//PackDoubleVolume 略。双代价背包
	//PackGroup 略。分组背包
	//PackGeneralize 略。泛化物品背包
	//PackDepend 略。赖背包(仅限森林)
	return true;
}
bool test4()
{
	return testStlBasicOpt() && testMonotonicStack() && testMinStack() && testMaxStack() && testMonotonicQueue() && testMaxQueue() && testQueueWithNoSameData() && testPack();
}

int main()
{
	if (test1() && test2() && test3() && test4())cout << "test succ!";
	return 0;
}

你可能感兴趣的:(算法)