set的相关知识点:重点是去重和排序!!!
默认按照升序排列!!!
set的常见操作:
1. 定义:set<数据类型>name;
2. 与map不同,count使用来判别一个元素是否存在在set中
name.count(x);
3. name.insert(x);
4. name.erase(x);//插入和删除都要注意迭代器失效!!!
erase函数返回被删除元素的下一个元素的迭代器。
erase(iterator) ,删除定位器iterator指向的值
erase(first,second),删除定位器first和second之间的值
erase(key_value),删除键值key_value的值
5. name.size();
1. http://acm.nefu.edu.cn/contestShow.php
第一点要设置集合数组!!!
第二点找两个集合中相同数目的个数的方法:
int k=0;
for(set::iterator it=vis[num1].begin(); it!=vis[num1].end(); it++)
if(vis[num2].count(*it)) k++;
#include <bits/stdc++.h>
using namespace std;
set<int>vis[52];
int main()
{
int n,m,num,num1,num2,x;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&num);
while(num--)
{
scanf("%d",&x);
vis[i].insert(x);
}
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&num1,&num2);
int k=0;
for(set<int>::iterator it=vis[num1].begin(); it!=vis[num1].end(); it++)
if(vis[num2].count(*it)) k++;
int ans=vis[num1].size()+vis[num2].size()-k;
printf("%.2lf%%\n",double(k)*100.00/ans);
}
return 0;
}
2. http://acm.nefu.edu.cn/contestShow.php
第一点是要理解举行训练的时候是用全集筛出每个成员没做过的题目,留下的就是训练题,举行比赛的时候要从全集中筛出每个成员做过的题目,留下的题目就是比赛题。
第二点是在每种情况下,一定要一个一个输入成员的编号,一个成员一个成员的去筛出。
第三点是如何筛出?通过count判断某个元素是否存在!!!详细见代码。
第四点是两个集合可以通过等号赋值!!!
#include <bits/stdc++.h>
using namespace std;
int n,m,k,cnt,x,num,cot,y;
set<int>vis[1010],all,ans;
set<int>::iterator it;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d",&num);
while(num--)
{
scanf("%d",&x);
vis[i].insert(x);
}
}
for(int j=1; j<=m; j++)
all.insert(j);
scanf("%d",&k);
for(int t=1; t<=k; t++)
{
ans=all;//两个集合之间可以用等号赋值!!!
scanf("%d%d",&cnt,&cot);
if(cnt==0)
{
for(int h=1;h<=cot;h++)
{
scanf("%d",&y);
for(it=ans.begin(); it!=ans.end(); )
{
if(vis[y].count(*it))
it=ans.erase(it);
else
it++;
}
}
}
else
{
for(int h=1;h<=cot;h++)
{
scanf("%d",&y);
for(it=ans.begin(); it!=ans.end(); )
{
if(!vis[y].count(*it))
it=ans.erase(it);
else
it++;
}
}
}
for(it=ans.begin(); it!=ans.end(); it++)
printf("%d ",*it);
printf("\n");
}
return 0;
}
3. http://acm.nefu.edu.cn/contestShow.php
#include <bits/stdc++.h>
using namespace std;
set<int>s;
set<int>::iterator it;
int n,x,ans=1;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
if(s.empty())s.insert(x);
else
{
it=s.upper_bound(x);//it是set容器中第一个大于x的迭代器
if(it==s.end())
//x比set容器中的所有数都要大,将x插入,需要增加铁轨
{
s.insert(x);
ans++;
}
else
//x插入到已有的铁轨中合适的位置,删除大于x的第一个数(*it),插入x
{
s.erase(*it);
s.insert(x);
}
}
}
printf("%d\n",ans);
return 0;
}
迭代器失效的一些总结:
1)增加元素到容器后
对于vector和string,如果容器内存被重新分配,iterators,pointers,references失效;如果没有重新分配,那么插入点之前的iterator有效,插入点之后的iterator失效;
对于deque,如果插入点位于除front和back的其它位置,iterators,pointers,references失效;当我们插入元素到front和back时,deque的迭代器失效,但reference和pointers有效;
对于list和forward_list,所有的iterator,pointer和refercnce有效。
(2)从容器中移除元素后
对于vector和string,插入点之前的iterators,pointers,references有效;off-the-end迭代器总是失效的;
对于deque,如果插入点位于除front和back的其它位置,iterators,pointers,references失效;当我们插入元素到front和back时,off-the-end失效,其他的iterators,pointers,references有效;
对于list和forward_list,所有的iterator,pointer和refercnce有效。
(3)在循环中refresh迭代器
当处理vector,string,deque时,当在一个循环中可能增加或移除元素时,要考虑到迭代器可能会失效的问题。我们一定要refresh迭代器。
(4)在循环不变式中不要store off-the-end迭代器
这个很容易理解了,增加或移除元素之后,off-the-end失效了,不store的话,每次从end()函数中取的都是最新的off-the-end,自然不会失效。