K. Keep In Line
又到饭点了,SK同学靠着惯性走到了食堂,但长长的队伍顿时让他失去了食欲。突然,他注意到某个窗口前的队伍里明显存在插队的现象,于是他默默记录下了同学们进队和出队的变化。
对于进队,SK同学只知道队伍里多了一个人,并不知道新来的人是老老实实站到了队尾还是插到了队伍里的某个位置;对于出队,SK同学能确定是队伍里站在最前面的人出队了。
初始时队伍为空,给出条队伍进出的信息,保证已经出队的同学不会再入队,并且最终队伍也为空,现在SK同学想知道有多少不插队的好同学。
Input
第一行是一个正整数,表示测试数据的组数,
对于每组测试数据,
第一行是一个整数,表示这个队伍进出的信息数,
接下来行,每行是两个字符串Opt Name,其中Opt为"in"代表进队,"out"代表出队,Name为进队或出队的人的名字,
所有信息按照时间顺序给出,名字由英文字母和阿拉伯数字组成,长度不超过,保证每个人的名字各不相同。
Output
对于每组测试数据,输出一行,包含一个整数,表示不插队的人数。
Sample Input
1 6 in quailty in hwq1352249 out hwq1352249 in zhuaiballl out quailty out zhuaiballl
Sample Output
2
思路:
按照题意模拟。
我们维护一个队列,in操作直接在队尾加入这个人,out操作先将之前插队了的在队头的所有元素都去掉,然后再判断当前队头和out操作这个人是否相等,如果相等,那么output++
否则标记这个人在队列中是插队的,将其置为队内无用元素即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
int vis[1008000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int tot=0;
int cnt=1;
queue<int >que;
map<string,int >s;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
char op[45];
char name[45];
scanf("%s%s",&op,&name);
if(s[name]==0)
{
s[name]=cnt;
cnt++;
}
if(op[0]=='i')
{
que.push(s[name]);
}
else
{
while(!que.empty())
{
int u=que.front();
if(vis[u]==1)que.pop();
else break;
}
if(que.size()>0&&que.front()==s[name])tot++,que.pop();
else vis[s[name]]=1;
}
}
printf("%d\n",tot);
}
}