Simons and Posting Blogs
题目大意
发布一篇博客时,会按顺序处理博客里提到的用户:
- 如果这个用户已经在 当前队列 QQ 里,就把它移动到 QQ 的最前面(“提到”一次,相当于“激活”一下它)。
- 如果这个用户不在 QQ 里,就把它插入到 QQ 的最前面。
我们要选择 博客发布的顺序,使得最终 QQ 的字典序最小。
代码
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
void so(){
int n;cin>>n;
vector<vector<int>>a(n,vector<int>{});
for(int i=0;i<n;i++){
int l;cin>>l;
set<int>st;
for(int j=0;j<l;j++){
int x;cin>>x;a[i].push_back(x);
}reverse(a[i].begin(),a[i].end());
vector<int>rep;
for(int j=0;j<l;j++){
if(st.empty()||st.find(a[i][j])==st.end()){
rep.push_back(a[i][j]);
st.insert(a[i][j]);
}
}a[i]=rep;
}sort(a.begin(),a.end());
vector<int>ans;
map<int,int>seen;
while(true){
if(a.empty())break;
for(int i:a[0]){
if(seen[i]==0){
seen[i]=1;
ans.push_back(i);
}
}vector<vector<int>>repp;
for(int i=1;i<a.size();i++){
vector<int>rep;
for(int j=0;j<a[i].size();j++){
if(!seen[a[i][j]])rep.push_back(a[i][j]);
}repp.push_back(rep);
}a=repp;
sort(a.begin(),a.end());
}
for(int i:ans){cout<<i<<' ';}
cout<<'\n';
}int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){so();}
}
思路
1.总体思路:把b[i]逆序后排序,字典序小的优先出现,然后去掉已经出现过的,重复这一过程(由数据大小知)
stl
1. set
set<int> st;
st.empty()
st.find(a[i][j]) == st.end()
st.insert(a[i][j])
- 有序集合,元素不重复,自动排序(默认升序)。
st.empty():判断集合是否为空。st.find(x):查找x,返回迭代器,如果没找到返回st.end()。st.insert(x):插入元素,如果已存在则插入失败(但这里没检查返回值)。
在这里用于 去除同一篇博客内重复的用户(只保留第一次出现的)。
2. map
map<int,int> seen;
seen[i] == 0
seen[i] = 1
- 键值对映射,自动按键排序。
map<int,int>的键是用户 ID,值是标记(0 未出现,1 已出现)。seen[i]:如果键i不存在,会默认初始化为 0(因为int的默认构造是 0)。- 用来标记一个用户是否已经被加入最终答案。
3. sort
sort(a.begin(), a.end());
- 排序算法,默认升序。
- 对
vector<vector<int>>排序时,按字典序比较两个vector<int>。 - 这里用于每次循环后重新排序剩余博客,保证每次取第一个博客(即当前字典序最小的博客)来处理。