一、基础知识
👉set
*要注意用迭代器(vector、set…)指向值的删除操作!
错误的删除操作👇
上图的操作会把迭代器删除!!
it的指向就空了!!
于是会出现下图警示👇
正确的操作👇
for (it = ans.begin(); it != ans.end();)
{
if (!ssr[t].count(*it))
ans.erase(it++);
else
it++;
}
二、习题&题解
A 明明的随机数-set [60/101]
#include <bits/stdc++.h>
using namespace std;
set<int> ssr;
set<int>::iterator it;
int n, x;
int main()
{
while (cin >> n)
{
for (int i = 1; i <= n; i++)
{
cin >> x;
ssr.insert(x);
}
cout << ssr.size() << endl;
for (it = ssr.begin(); it != ssr.end(); it++)
it == ssr.begin() ? cout << *it : cout << " " << *it;//按格式输出
ssr.clear();
cout<<endl;
}
//system("pause");
return 0;
}
B 第K小整数-SET [57/89]
#include <bits/stdc++.h>
using namespace std;
set<int> ssr;
set<int>::iterator it;
int n, k, x;
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> x;
ssr.insert(x);
}
if (k <= ssr.size())
{
it = ssr.begin();
k = k - 1;
while (k--)
it++;
cout << *it << endl;
}
else
cout << "NO RESULT";
//system("pause");
return 0;
}
C 单词记忆-set-map [55/63]
#include <bits/stdc++.h>
using namespace std;
set<string> ssr;
string str;
int n, x;
int main()
{
cin >> n;
while (n--)
{
cin >> x;
if (x == 0)
{
cin >> str;
ssr.insert(str);
}
else
{
cin >> str;
if (ssr.count(str))
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
//system("pause");
return 0;
}
D 列车调度-SET [32/67]
所有的路都必须从右往左(按示例图说的)递减才能排出来。例如输入:
9
8 4 2 5 3 9 1 6 7
先存8,再输入4,4比8小,用4代替8(递减排的要求),2代替4;
再碰到5,得新开一条路,于是存进去,计数器加一……
注意,因为是最少路数,所以用的upper_bound;
所以最终四条路是这样的:(删除线表示依次被替换)
8 4 2 1
5 3
9 6
7
(打算用纯数组写弄了将近两个小时也没AC,老老实实set吧)
#include <bits/stdc++.h>
using namespace std;
set<int> ssr;
set<int>::iterator it;
int n, x, ans;
int main()
{
cin >> n;
while (n--)
{
cin >> x;
if (ssr.size() == 0)
{
ssr.insert(x);
ans++;
}
else
{
it = ssr.upper_bound(x);
if (it != ssr.end())
{
ssr.insert(x);
ssr.erase(*it);
}
else
{
ssr.insert(x);
ans++;
}
}
}
cout << ans;
//system("pause");
return 0;
}
E 相似的数集简单版-SET [31/88]
这题主要是题意不明。
意思应该是去掉单个集合内重复的数,然后再看两个集合中有几对相等的数,分母就是去重后的元素个数减去相同的对数(我也不知道这从题目是怎么推出来的,只能从输入输出一种关系一种关系的试)
#include <bits/stdc++.h>
using namespace std;
set<int> ssr[51]; //set数组
int n, m, x;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> m;
while (m--)
{
cin >> x;
ssr[i].insert(x);
}
}
int k;
cin >> k;
while (k--)
{
int set1, set2, anscnt = 0;
cin >> set1 >> set2;
for (set<int>::iterator it = ssr[set1].begin(); it != ssr[set1].end(); it++)
if (ssr[set2].count(*it))
anscnt++;
double ans = anscnt * 1.0 / (ssr[set1].size() * 1.0 + ssr[set2].size() * 1.0 - anscnt * 1.0) * 100.0;
printf("%.2lf%\n", ans);
}
//system("pause");
return 0;
}
F NOIP 题海战-SET-1 [10/64]
这题不难,但卡了我很久,原因就是上面的特别注意部分/大哭
以至于我都没心情写注释了,应该还好懂吧
#include <bits/stdc++.h>
using namespace std;
set<int> ssr[1005], ans;
set<int>::iterator it;
int n, m, x, t;
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &x);
while (x--)
{
scanf("%d", &t);
ssr[i].insert(t);
}
}
int k, s, n2;
scanf("%d", &k);
for (int i = 1; i <= m; i++)
ssr[1002].insert(i);
while (k--)
{
scanf("%d%d", &s, &n2);
ans = ssr[1002];
if (s == 0)
{
for (int i = 1; i <= n2; i++)
{
cin >> t;
for (it = ans.begin(); it != ans.end();)
{
if (ssr[t].count(*it))
ans.erase(it++);
else
it++;
}
}
}
else
{
for (int i = 1; i <= n2; i++)
{
cin >> t;
for (it = ans.begin(); it != ans.end();)
{
if (!ssr[t].count(*it))
ans.erase(it++);
else
it++;
}
}
}
for (it = ans.begin(); it != ans.end(); it++)
printf("%d ", *it);
printf("\n");
}
//system("pause");
return 0;
}