B2. Social Network (hard version)(STL)Codeforces Round #590 (Div. 3)

原题链接:https://codeforces.com/contest/1234/problem/B2

你正在一个流行的社交网络中通过智能手机发送信息。你的智能手机最多可以显示k个最近与朋友的对话。最初,屏幕是空的(即显示的对话数等于0)。 每次谈话都是你和你的一些朋友之间的。最多只能和你的朋友进行一次谈话。所以每次谈话都是由你的朋友来定义的。 现在你(突然!)有能力看到未来。你知道在一天中你将收到n条信息,第i条信息将从id为idi(1≤idi≤10^9)的朋友处收到。 如果在智能手机当前显示的对话中收到来自IDI的消息,则不会发生任何事情:屏幕上的对话不会更改,也不会更改其顺序,您将阅读该消息并继续等待新消息。 否则(即,如果屏幕上没有与IDI的对话): 首先,如果屏幕上显示的对话数为k,则从屏幕上删除最后一个对话(位置为k)。 现在,屏幕上的对话数保证小于k,并且与朋友idi的对话不会显示在屏幕上。 与朋友idi的对话出现在屏幕的第一个(最上面的)位置,所有其他显示的对话都向下移动一个位置。 你的任务是在处理完所有n条消息后查找对话列表(按对话在屏幕上显示的顺序)


Input
输入的第一行包含两个整数n和k(1≤n,k≤2e5)-您的智能手机可以显示的消息数和对话数。 输入的第二行包含n个整数id1,id2,…,idn(1≤id i≤10^9),其中idi是向您发送第i条消息的朋友的id。
Output
在输出的第一行中,打印一个整数m(1≤m≤m in(n,k))——接收所有n条消息后显示的会话数。 在第二行中,打印m个整数ids1、ids2、…、idsm,其中idsi应等于收到所有n条消息后显示在位置i上的对话对应的朋友的id。


Examples
Input
7 2
1 2 3 2 1 3 2
Output
2
2 1
Input
10 4
2 3 3 1 1 2 1 2 3 3
Output
3
1 3 2


注:这是有两个题的,只不过一个题增加了范围而已,我这里贴的是范围较大的那个题。

题意:你会不断收到n条信息,遵循先来后到的原则,先来的占前面位置,后来的往后移,遵循有了就叠加的规则,窗口最多只能显示k条信息,问最后接受完信息后屏幕上还剩多少条,输出这些信息。

解题思路:这明显就是一个入队+出队的问题,但这里还要注意一个小细节,已经入队了的就不用入队了,所以我们还要作标记,可以使用visited数组来实现标记,也可以利用map来标记,我比赛的时候用的是map,没想太多,这里其实用visited更简单一点,入队和出队均改标记即可。那么最后输出的时候是要从队尾开始输出的,所以我们可以使用双端队列deque,或者利用栈来转移输出操作


AC代码:

/*
*邮箱:2825841950@qq.com
*blog:https://blog.csdn.net/hzf0701
*注:代码如有问题请私信我或在评论区留言,谢谢支持。
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>
#include<memory.h>//低版本G++编译器不支持,若使用这种G++编译器此段应注释掉
#include<iomanip>
#include<vector>
#include<cstring>
#define scd(n) scanf("%d",&n)
#define scf(n) scanf("%f",&n)
#define scc(n) scanf("%c",&n)
#define scs(n) scanf("%s",n)
#define prd(n) printf("%d",n)
#define prf(n) printf("%f",n)
#define prc(n) printf("%c",n)
#define prs(n) printf("%s",n)
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 2e5+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为代码自定义代码模板***************************************//

int main(){
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	ios::sync_with_stdio(false);//打消iostream中输入输出缓存,节省时间。
	cin.tie(0); cout.tie(0);//可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。
	ll n,k;
	ll id[maxn];
	while(cin>>n>>k){
        rep(i,0,n-1){
            cin>>id[i];
        }
        map<ll,ll> p;
        queue<ll>  q;
        ll temp1,temp2;
        rep(i,0,n-1){
            if(!p[id[i]]){
                q.push(id[i]);
            }
            temp2=q.size();//判断消息列表是否满了。
            p[id[i]]++;
            if(temp2>k){
                temp1=q.front();
                p.erase(temp1);
                q.pop();
            }
        }
        cout<<q.size()<<endl;
        stack<ll> s;
        while(!q.empty()){
            s.push(q.front());
            q.pop();
        }
        while(!s.empty()){
            cout<<s.top()<<" ";
            s.pop();
        }
        cout<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

unique_pursuit

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值