非常典型的csp之用stl数据结构xjb乱搞的题。要执行的操作是增加删除和查询,考虑到输入规模,每次操作的复杂度必须是log的(当然可m可以看作比较小的常数)。优先队列可以很好地实现插入和查询,但是删除的话最坏复杂度是O(n)的,pass。因此只剩下一个选择,就是set。因为这个题的输入保证商品两两不同(综合score,id和type一起看的话)因此不用multiset,只用普通的set即可。考虑到商品得分相同时的选取原则,排序策略为:
bool operator < (const good & o) const {
if(score != o.score) return score > o.score;
else if(cate != o.cate) return cate < o.cate;
else return id < o.id;
}
这样就能保证满足条件的最优选取原则了。
具体来说,对于插入操作,直接构造结构体然后插入set,同时把type和id构成的pair为键对应的值设置为score(方便二分查找);对于删除操作,根据输入的type和id找到score,然后根据这三者创建结构体,在set中二分查找并删除;对于查询操作,按照题意遍历set模拟即可。
#include <bits/stdc++.h>
using namespace std;
int n, m;
struct good {
int cate, id, score;
bool operator < (const good & o) const {
if(score != o.score) return score > o.score;
else if(cate != o.cate) return cate < o.cate;
else return id < o.id;
}
};
set<good> s;
int cnt[100005];
map<pair<int,int>, int> mp;
int K, k[500];
vector<int> ans[505];
int main() {
cin >> m >> n;
for(int i = 1; i <= n; i++) {
int id, score;
scanf("%d%d", &id, &score);
for(int j = 1; j <= m; j++) {
good tmp;
tmp.id = id, tmp.score = score;
tmp.cate = j - 1;
s.insert(tmp);
pair<int, int> pii = make_pair(j - 1, id);
mp[pii] = score;
}
}
int opnum;
cin >> opnum;
for(int i = 0; i < opnum; i++) {
int op;
scanf("%d", &op);
if(op == 1) {
int type, commodity, score;
scanf("%d%d%d", &type, &commodity, &score);
good tmp;
tmp.cate = type, tmp.id = commodity, tmp.score = score;
pair<int, int> pii = make_pair(type, commodity);
mp[pii] = score;
s.insert(tmp);
} else if(op == 2) {
int type, commodity;
scanf("%d%d", &type, &commodity);
pair<int, int> pii = make_pair(type, commodity);
good cpy;
cpy.cate = type, cpy.id = commodity, cpy.score = mp[pii];
multiset<good>::iterator it = s.lower_bound(cpy);
if(it != s.end()) s.erase(it);
mp.erase(pii);
} else {
scanf("%d", &K);
for(int j = 0; j < m; j++) {
scanf("%d", &k[j]);
ans[j].clear();
}
vector<good> tmp;
int tot = 0;
for(auto x : s) {
if(tot == K) break;
if(ans[x.cate].size() < k[x.cate]) {
ans[x.cate].push_back(x.id);
tot++;
} else {
continue;
}
}
for(int j = 0; j < m; j++) {
if(ans[j].size()) {
for(int p = 0; p < ans[j].size(); p++) {
if(p != ans[j].size() - 1) printf("%d ", ans[j][p]);
else printf("%d\n", ans[j][p]);
}
} else {
puts("-1");
}
}
}
}
return 0;
}
// 2 3
// 1 3
// 2 2
// 3 1
// 8
// 3 100 1 1
// 1 0 4 3
// 1 0 5 1
// 3 10 2 2
// 3 10 1 1
// 2 0 1
// 3 2 1 1
// 3 1 1 1