目录
〇,全文说明、宏定义代码
一,输入输出
二,vector
三,链表
四,STL操作封装、拓展数据结构、背包
五,test
类里面和宏定义处都有接口注释,因为宏不体现具体参数,所以注释以类里面的为准。
所有代码放在一起是可以编译运行的,如果按照章来划分,最后一章是测试代码,其他任意一章都可以单独编译运行。
宏定义代码:
#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)含容器的自定义数据结构
};
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;
}
};
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);
}
};
#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;
}