https://oi-wiki.org/lang/csl/associative-container/
1.基本操作
2.自定义比较方式
P5250 【深基17.例5】木材仓库 set/ multiset
#include<iostream>
#include<set>
using namespace std;
int t, x, y;
set<int> s; //由于不重复放置,这里写成multiset也可以
int main(){
scanf("%d",&t);
for(int i = 1; i <= t; i++){
scanf("%d%d",&x,&y);
if(x == 1){
if(s.find(y) != s.end()) printf("Already Exist\n");
else s.insert(y);
}else{
if(s.empty()){
printf("Empty\n");continue;
}
set<int>::iterator it, ip;
it = ip = s.lower_bound(y);
if(it == s.begin()){
printf("%d\n",*it); s.erase(it); //所有的erase都少了*
}
else if(it == s.end()){
printf("%d\n",*(--it)); s.erase(it);
}
else if(y - (*(--it)) <= (*ip) - y){
printf("%d\n",*it); s.erase(it);
}
else{
printf("%d\n",*ip); s.erase(ip);
}
}
}
return 0;
}
/*
13
1 5
1 5
1 5
1 5
1 5
2 5
2 5
2 5
2 5
2 5
1 100000
1 1
2 5
*/
POJ 3481 Double Queue
【问题描述】
每个顾客有个编号和优先级,银行每次可以添加顾客的要求进队列,且保证队列中当
前任意顾客的编号和优先级都不同。银行可以执行先服务最大优先级的顾客或者先服务最
小优先级的顾客操作。对于每个服务,输出顾客的编号。
存在以下操作:
1 K P 增加编号为 K,优先级为 P 的顾客到等待队列中;
2 服务优先级最大的顾客,且将其从等待队列中取出;
3 服务优先级最小的顾客,且将其从等待队列中取出;
【输入格式】
每行输入一个请求,最后以输入 0 结束,输入格式如题目描述。
你可以假设,当操作为 1 时,不会同时存在相同的客户编号 K,或者相同的优先级 P。 (𝐾 ≤ 106, 𝑃 ≤ 107)同一个客户可以多次进入等待队列,以不同的优先级。
【输出格式】
对于每个 2 和 3 的请求时,输出顾客编号,如果遇到等待队列为空,输出0。
分析:
本题要求处理银行排队问题,根据每行的输入处理数据;若输入为1则继续输入两个整数,以第一个数为权值,第二个数为优先级(数值越大优先级越高)加入排队系统中;若输入为2 则处理当前优先级最高的用户,并输出用户的权值;若输入为3 则处理当前优先级最低的用户,并输出用户权值;若输入为0结束运行。若当没有排队人数则无论输入2、3都输出0。
利用set自带红黑树排序的性质,可以在集合中直接获取最高与最低优先级,用pair记录权值和优先级,将pair传入集合。用迭代器可以获得集合首位(最大优先级)和集合末尾(最小优先级),数据处理完毕后可以通过erase()删除当前用户以便后续操作。
set 结构体.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<set>
using namespace std;
struct Node{
int id, pri;
Node(){};
Node(int x, int y):id(x),pri(y){}
bool operator < (const Node &y) const{
return pri > y.pri;
}
};
set<Node> st;
int main(){
int n,x,y;
while(scanf("%d",&n) != EOF){
if(n == 0) break;
if(n == 1){
scanf("%d%d",&x, &y);
st.insert(Node(x,y));
set<Node>::iterator it = st.begin();
// cout<<"begin "<<(*it).pri<<endl;
}
if(n == 2){
if(!st.empty()){
set<Node>::iterator it = st.begin();
printf("%d\n",(*it).id);
st.erase(it);
}
else{
printf("0\n");
}
}
if(n == 3){
if(!st.empty()){
set<Node>::iterator it = st.end();
it--;
printf("%d\n",(*it).id);
st.erase(it);
}
else{
printf("0\n");
}
}
};
return 0;
}
双关键字set排序,set返回第一个关键字大的位置,第二个不一定大,如果第一个关键字和查询的一样大,则返回第二个关键字大的位置
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
using namespace std;
#define INF 0x3f3f3f3f
int main()
{
set<pair<int,int> > s;
s.insert(make_pair(3,1));
s.insert(make_pair(3,2));
s.insert(make_pair(1,8));
s.insert(make_pair(1,2));
s.insert(make_pair(3,5));
s.insert(make_pair(2,6));
set<pair<int ,int> > ::iterator it;
for(it=s.begin();it!=s.end();it++){
cout<<it->first<<' '<<it->second<<"\n";
cout<<(*it).first<<" "<<(*it).second<<endl;
}
it=s.lower_bound(make_pair(3,-1));
if(it!=s.end())
printf("(3,-1)后面接着是%d %d\n",it->first,it->second);
}
P8686 修改数组
逆向思维,排区间的右端点
#include <iostream>
#include <set>
using namespace std;
typedef pair<int, int > PII;
const int N = 5e5 + 10;
int cnt[N];
set<PII>q;
void insert(int l, int r) {
if (l < r) return;
q.insert(make_pair(l, r));
}
int main() {
int n;
cin >> n;
q.insert(make_pair(2e9 + 10, 1));
for (int i = 0; i < n; i++) {
cin >> cnt[i];
set<PII>::iterator it;
it = q.lower_bound(make_pair(cnt[i], 0));//error (cnt[i], cnt[i])
if (it->second <= cnt[i]) {
cout << cnt[i] << ' ';
insert(cnt[i] - 1, it->second);
insert(it->first, cnt[i] + 1);
q.erase(it);
}
else {
cout << it->second << ' ';
insert(it->first, it->second + 1);
q.erase(it);
}
}
}
/*
5 10 15
[1,4] [6,9] [11,15]
4
5 10 15 9err
*/
sdfzoj庐州月
和逆序对比较像,两个关键字,把一个关键字比自己大挑出来,对应的另一个关键字放set里,查询另一个关键字比自己大的元素
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
int n,m,x,y; ll sum;
multiset<int> st;
multiset<int> :: iterator it;
struct Node{
int x,y;
}a[100005], b[100005];
bool cmp(Node p, Node q){
if(p.y == q.y) return p.x > q.x;
return p.y > q.y;
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) scanf("%d%d",&a[i].x,&a[i].y);
for(int i = 1; i <= m; i++) scanf("%d%d",&b[i].x,&b[i].y);
sort(b+1, b+m+1, cmp); sort(a+1, a+n+1, cmp);
int j = 1;
for(int i = 1; i <= n; i++){
for(;j <= m; j++){
if(b[j].y >= a[i].y) st.insert(b[j].x);
else break;
}
it = st.lower_bound(a[i].x);
sum += (*it);
st.erase(it);
}
cout<<sum<<endl;
return 0;
}
/*
(2,6)(5,4)(4,4)(4,3)(5,2)(3,2)(2,1)
(1,4)(2,3)(4,2)(1,1)
*/