CSP推荐系统及set用法总结

2 篇文章 0 订阅
1 篇文章 0 订阅


最近对set的使用频繁掉坑,所以做一个总结


一、set的erase()

set的erase()可删除单个元素也可删除一个区间的元素
例如:

`set<int>s;
 for(int i=0;i<10;i++)s.insert(i);
 s.erase(s.find(1));
 s.erase(s.begin(),s.end());

详解链接

二、set中结构体自定义去重和排序函数

1.详解

set和map的内部实现都是红黑树,默认排序都是从小到大。但是有时用到的元素是结构体而不是基本类型,就需要自定义排序,不然就会报错。自定义排序就需要重载<。再提一点priority_queue是默认优先级大的排前面,所以默认排序是从大到小。
详解传送门
这里有大佬讲得很详细。总结一点set的去重,在重载operator<时,让相同的两个对象总是返回false。(因为set是通过交换两个元素的左右位置,根据返回的值判断两个元素是否相同)

2.CSP推荐系统(自定义的注意事项)

但是很有意思的一件事情是,我在做csp推荐系统这道题时,定义了如下结构体:
我的本意是,不管score的值如何,只要type和id相同则判断是同一个元素

struct node
{
	int type;
	int id;
	int score;
	friend	bool operator<(node n1, node n2)
	{
		if (n1.type == n2.type&&n1.id == n2.id)//type,id均相同则判断为同一元素 
		{
			return false;
		}
		if (n1.score != n2.score)
		{
			return n1.score >n2.score;
		}
		else if (n1.type != n2.type)
		{
			return n1.type < n2.type;
		}
		else
		{
			return n1.id< n2.id;
		}
	}
};

在后面的代码中有对set中元素的删除操作,我的目的是根据type和id查找到某一元素,并将其删除(没有对score进行处理)。神奇的事情发生了,这样操作在devc下可以将对应type和id值相同的元素删除,但是在vs下却不可以。并且我在csp的oj系统上提交该代码,爆零。

	int type, id;
	scanf("%d%d", &type, &id);
    node temp;
	temp.type = type;
	temp.id = id;
	set<node>::iterator it = products.find(temp);
	if (it != products.end())products.erase(it);

完整代码如下

#include<iostream>
#include<vector>
#include<set>
#pragma warning (disable:4996)
using namespace std;
int k[100], procount[100];
int m, n, K;
vector<int> query[100];
struct node
{
	int type;
	int id;
	int score;
	friend	bool operator<(node n1, node n2)
	{
		if (n1.type == n2.type&&n1.id == n2.id)//type,id均相同则判断为同一元素 
		{
			return false;
		}
		if (n1.score != n2.score)
		{
			return n1.score >n2.score;
		}
		else if (n1.type != n2.type)
		{
			return n1.type < n2.type;
		}
		else
		{
			return n1.id< n2.id;
		}
	}
};
//vector<node> goods;
set<node> products;

int main()
{
	scanf("%d%d", &m, &n);
	for (int i = 0; i < n; i++)
	{
		int id, score;
		scanf("%d%d", &id, &score);
		for (int j = 0; j < m; j++)
		{
			//goods.push_back(node{j,id,score});
			products.insert(node{ j,id,score });
		}
	}
	int opnum;
	scanf("%d", &opnum);

	for (int i = 0; i < opnum; i++)
	{
		//char str[2];
		//getchar();
		int op;
		scanf("%d", &op);
		if (op == 1)
		{
			int type, id, score;
			scanf("%d%d%d", &type, &id, &score);
			products.insert(node{ type,id,score });
		}
		if (op == 2)
		{
			int type, id;
			scanf("%d%d", &type, &id);
			node temp;
			temp.type = type;
			temp.id = id;
			set<node>::iterator it = products.find(temp);
			if (it != products.end())products.erase(it);
		}
		if (op == 3)
		{
			scanf("%d", &K);
			for (int j = 0; j < m; j++)
			{
				scanf("%d", &k[j]);
			}
			int totcount = 0;
			for (set<node>::iterator iit = products.begin(); iit != products.end(); iit++)
			{
				node pro = *iit;
				int u = pro.type;
				if (procount[u] < k[u])
				{
					procount[u]++;
					totcount++;
					query[u].push_back(pro.id);
					if (totcount == K)break;
				}
			}
			for (int mm = 0; mm < m; mm++)
			{
				if (query[mm].size() != 0)
				{
					for (int ii = 0; ii < query[mm].size(); ii++)
					{
						printf("%d ", query[mm][ii]);
					}
				}
				else
				{
					printf("-1");
				}
				query[mm].clear();
				printf("\n");
			}
			fill(procount, procount + 100, 0);
		}
	}
	system("pause");
	return 0;
}

之后我用另一个set单独存储了删除元素,代码就AC了

代码如下:

#include<iostream>
#include<vector>
#include<set>
#pragma warning (disable:4996)
using namespace std;
int k[100], procount[100];
int m, n, K;
vector<int> query[100];
struct node
{
	int type;
	int id;
	int score;
	friend	bool operator<(node n1, node n2)
	{
		if (n1.type == n2.type&&n1.id == n2.id)
		{
			return false;
		}
		if (n1.score != n2.score)
		{
			return n1.score >n2.score;
		}
		else if (n1.type != n2.type)
		{
			return n1.type < n2.type;
		}
		else
		{
			return n1.id< n2.id;
		}
	}
};
struct delNode
{
	int type;
	int id;
	friend	bool operator<(delNode n1, delNode n2)
	{
	    if (n1.type != n2.type)
		{
			return n1.type < n2.type;
		}
		else
		{
			return n1.id< n2.id;
		}
	}
};
//vector<node> goods;
set<node> products;
set<delNode> delSet;

int main()
{
	scanf("%d%d", &m, &n);
	for (int i = 0; i < n; i++)
	{
		int id, score;
		scanf("%d%d", &id, &score);
		for (int j = 0; j < m; j++)
		{
			//goods.push_back(node{j,id,score});
			products.insert(node{ j,id,score });
		}
	}
	int opnum;
	scanf("%d", &opnum);

	for (int i = 0; i < opnum; i++)
	{
		//char str[2];
		//getchar();
		int op;
		scanf("%d", &op);
		if (op == 1)
		{
			int type, id, score;
			scanf("%d%d%d", &type, &id, &score);
			products.insert(node{ type,id,score });
		}
		if (op == 2)
		{
			int type, id;
			scanf("%d%d", &type, &id);
			//qnode temp;
		/*	temp.type = type;
			temp.id = id;
			set<node>::iterator it = products.find(temp);
			if (it != products.end())products.erase(it);
			*/
			delSet.insert(delNode{type,id});
		}
		if (op == 3)
		{
			scanf("%d", &K);
			for (int j = 0; j < m; j++)
			{
				scanf("%d", &k[j]);
			}
			int totcount = 0;
			for (set<node>::iterator iit = products.begin(); iit != products.end(); iit++)
			{
				node pro = *iit;
				int u = pro.type;
				set<delNode>::iterator ii=delSet.find(delNode{pro.type,pro.id});
				if(ii!=delSet.end())continue;//注意是不等于的时候continue 
				if (procount[u] < k[u])
				{
					procount[u]++;
					totcount++;
					query[u].push_back(pro.id);
					if (totcount == K)break;
				}
			}
			for (int mm = 0; mm < m; mm++)
			{
				if (query[mm].size() != 0)
				{
					for (int ii = 0; ii < query[mm].size(); ii++)
					{
						printf("%d ", query[mm][ii]);
					}
				}
				else
				{
					printf("-1");
				}
				query[mm].clear();
				printf("\n");
			}
			fill(procount, procount + 100, 0);
		}
	}
//	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值