[STL]set(转载)
维护集合信息,集合内各元素均不相同,支持插入、删除、查询等操作,单次操作复杂度为O(logN)。
set能根据待定的排序准则自动将元素排序。默认比较方式是less。
构造set集合主要目的是为了快速检索,不可直接去修改键值。
常用操作:
1.元素插入:insert()
set<int> S;
S.insert(13); //插入元素
2.按序遍历:用迭代器遍历
set<int> S;
set<int>::iterator it;
for (it = S.begin(); it != S.end(); ++it) // 不支持it+=3这样的操作
cout << *it << " "; // 递增输出,如1 3 4 6
3.反向遍历:利用反向迭代器reverse_iterator
set < int > s;
set< int >::reverse_iterator rit;
for(rit = s.rbegin(); rit != s.rend(); rit++)
4.元素删除:erase()
set< int > s;
s.erase(2); //删除键值为2的元素
s.clear(); //清空集合元素
5.元素检索:find()
,若找到,返回该键值迭代器的位置,否则,返回最后一个元素的后一个位置。
set<int> s;
set<int>::iterator it;
it=s.find(5); //查找键值为5的元素
if(it!=s.end()) //找到
cout<<*it<<endl;
else //未找到
cout<<"未找到";
6.自定义比较函数
(1)元素不是结构体, 可自定义比较函数myComp,重载“()”操作符:
struct myComp
{
bool operator()(const your_type &a,const your_type &b)
{
return a.data > b.data;
}
}
set<int,myComp>s;
set<int,myComp>::iterator it;
(2)如果元素是结构体,可以直接将比较函数写在结构体内。
struct Info
{
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const
{
//按score从大到小排列
return a.score<score;
}
}
set<Info> s;
set<Info>::iterator it;
7.返回某个值元素的个数count()
8.lower_bound() 和 upper_bound()
set<int> S;
set<int>::iterator it;
it = S.lower_bound(13); // 返回第1个小于等于13的元素的迭代器
if (it != S.begin())
--it; // 返回第1个小于13的元素的迭代器
it = S.upper_bound(13); // 返回第1个大于13的元素的迭代器
if (it != S.begin())
--it; // 返回第1个小于等于13的元素的迭代器
queue
通常用于spfa中,可以避免写循环队列(即一个点可能入队多次)。
// 最短路,spfa
int dis[N];
bool vis[N];
vector<pair<int, int> > edge[N]; // 邻接表
queue<int> que;
void bfs(int start) {
for (int i = 1; i < N; ++i)
dis[i] = INF, vis[i] = false;
dis[start] = 0, vis[start] = true, que.push(start);
while (!que.empty()) {
int u = que.front();
que.pop();
for (int i = 0; i < edge[u].size(); ++i) {
int v = edge[u][i].first, d = edge[u][i].second;
if (dis[v] > dis[u] + d) {
dis[v] = dis[u] + d;
if (!vis[v])
vis[v] = true, que.push(v); // 进队列
}
}
vis[u] = false; // 出队列
}
}
vector
存数据很方便,并且常用于数据离散化。
vector<int> e[N]; // 邻接表
for (int i = 0; i < m; ++i) { // 假设有m条边
int u, v;
scanf("%d%d", &u, &v);
e[u].push_back(v); // push_back()将元素添加到容器尾部
e[v].push_back(u);
}
for (int i = 0; i < e[u].size(); ++i) { // 遍历与u有连边的点
int v = e[u][i];
cout << v << " ";
}
//邻接表的数组实现
int et, head[N]; // head[]需要赋初值-1
struct Edge {
int t, d, nxt;
} e[M * 2]; // M为边数,无向边需要*2
void addEdge(int s, int t, int d) { // s -> t, 权值为d
e[et].t = t, e[et].d = d, e[et].nxt = head[s], head[s] = et++;
// 若为有向边,则这句去掉
e[et].t = s, e[et].d = d, e[et].nxt = head[t], head[t] = et++;
for (int i = head[u]; i != -1; i = e[i].nxt) { // 遍历与u有连边的点
int v = e[i].t, d = e[i].d;
cout << v << " ";
}
//今日代码
2016-07-18 personal training V2
A. Dubstep
(从字符串中删去多个指定字符串)
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
int main()
{
freopen("xx.in","r",stdin);
freopen("xx.out","w",stdout);
string s;
cin >> s;
for(int i = 0; i < s.length() ; i++)
{
if(s[i] == 'W' && s[i+1] == 'U' && s[i+2] == 'B')
{
s[i] = '0';
s[i+1] = '0';
s[i+2] = '0';
i+=2;
}
}
int i = 0;
while(s[i++] == '0');
int j = s.length()-1;
while(s[j--] == '0');
for(i = i-1;i<= j+1;i++)
{
if(s[i]!='0') cout << s[i];
else
{
cout <<" ";
while(s[i++]=='0');
i=i-2;
}
}
return 0;
}
D. Prizes, Prizes, more Prizes
(贪心。每次都从中尽量减去prize中最大的值,一次可能减去多次。)
#include<iostream>
#include<cstdio>
#include<string>
#include<map>
#include<algorithm>
#include<cmath>
#include<cstring>
#define LL __int64
using namespace std;
LL arr[55];
LL prize[10];
LL get[10];
bool compare(LL a,LL b)
{
return a > b;
}
int main()
{
freopen("xx.in","r",stdin);
freopen("xx.out","w",stdout);
int n;
cin >> n;
for(int i = 0 ; i < n; i++)
scanf("%I64d",&arr[i]);
for(int i = 0; i < 5; i++)
scanf("%I64d",&prize[i]);
LL sum = 0;
for(int i = 0; i < n; i++)
{
sum+=arr[i];
for(int j = 4; j >= 0; j--)
if(sum >= prize[j])
{
get[j]+=sum/prize[j];
sum %= prize[j];
}
}
cout << get[0];
for(int i = 1; i < 5; i++)
printf(" %I64d",get[i]);
printf("\n");
printf("%I64d\n",sum);
return 0;
}
F. System of Equations
(枚举。a,b都不为负数,一定小于m,n中的最小值。)
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
int main()
{
freopen("xx.in","r",stdin);
freopen("xx.out","w",stdout);
int n,m;
int a,b;
cin >> n >> m;
int x = min(n,m);
int cnt = 0;
for(a = 0; a <= x; a++)
for(b = 0; b <=x ;b++)
{
if(a*a+b == n && a+b * b ==m) cnt++;
}
cout << cnt << endl;
return 0;
}
G. Hometask
(从给定的一串数字中拼凑出最大的可以被2,3,5整除的数。能被2,5同时整除则尾数一定是0,所以所给数字不存在0时直接输出-1。能被3整除则各个位上数字和也能被3整除。若能从中找到一个数字%3的值和sum%3值相等,则删去这个数字就得到答案。若找不到,删去两个最小的%3不为零的数则为答案,因为比如sum%3=1,此时存在%3不为0的数则一定%3=2,删去两个即可;sum%3=2时同理。)
#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstring>
#define LL long long
using namespace std;
int cnt[100086];
int num;
int sum;
void check()
{
if(sum == 0) cnt[0] = 1; //避免多个0
for(int i= 9; i >= 0; i--)
while(cnt[i]--) printf("%d",i);
printf("\n");
}
int main()
{
freopen("xx.in","r",stdin);
freopen("xx.out","w",stdout);
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
scanf("%d",&num);
sum+=num;
cnt[num]++;
}
if(cnt[0] == 0) //no 0
{
cout << -1<< endl;
return 0;
}
else if(sum%3 == 0) //no delete
{
check();
return 0;
}
else //delete
{
for(int i = 0; i <= 9; i++)
if(cnt[i] && i%3 == sum%3) //delete1
{
sum-=i;
cnt[i]--;
break;
}
if(sum%3 == 0)
{
check();
return 0;
}
//delete2
int t=2;
while(t--)
{
for(int i = 0; i <=9 && sum%3; i++)
if(cnt[i] && i%3)
{
sum-=i;
cnt[i]--;
}
}
if(sum%3) printf("-1\n");
else check();
return 0;
}
}