题目1540:麦霸

题目1540:麦霸

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:75

解决:19

题目描述:

GrassLand酷爱K歌,俗称麦霸,每次去KTV他都会为自己点许多歌曲。
给定点唱机的操作序列,GrassLand希望知道他所点的每首歌曲将会在什么时间开始播放。
点唱机的操作主要是对点唱机已选列表的操作,包括:
1.top x,将已选列表中第x首歌曲,置于已选列表顶端。
2.delete x,将已选列表中第x首歌曲从已选列表中删除。数据保证前两种操作中的x不大于当时已选列表中歌曲的数目,已选列表头部的歌曲记为第一首。
3.add val flag,将一首长度为val(1<=val<=1000)的歌曲加入已选列表尾端,当flag为1时代表该首歌是GrassLand所点,为0时由他人所点。
点唱机每一秒的操作逻辑如下:
1.若当前没有歌曲正在播放,且已选列表不为空,则播放已选列表头部的歌曲,并将其从已选列表中删除;否则不进行任何操作。
2.响应用户的操作,并对已选列表进行相应操作。
3.若当前歌曲已经播放完毕,结束播放。注意,若一首长度为v的歌曲在时刻x时开始播放,则其播放时间为[x,x+v),也就是说,若没有其他操作发生,它会在时刻x+v-1时结束播放。
除此之外,点唱机还提供了一种,针对正在播放歌曲的操作:
1.cut,即设置当前正在播放的歌曲,在cut操作发生的时刻,播放完毕。若此时没有歌曲正在播放,则忽略该操作。
初始时为0时刻,点唱机没有正在播放的歌曲,已选列表为空。

输入:

输入包含多组测试用例,每组测试用例的开头为一个整数k(1<=k<=1000),代表共有k个点唱机操作。
接下去k行,每行描述一个操作,其格式为”t+如上四种操作中的一种“,t(1<=t<=1000000)表示该操作发生的时刻,如
3 top 2,表示在时刻3将已选列表中的第二首歌曲置顶。数据保证在一个时刻内仅一个操作,且输入数据按照t递增顺序给出。

输出:

对于每组测试用例输出若干行,代表GrassLand所点的歌曲开始播放的时间刻度(所有被正在播放过的歌曲),播放时间按照升序排列。

样例输入:
7
1 add 15 1
2 add 16 1
3 add 10 0
4 add 16 1
5 top 2
6 delete 3
7 cut
样例输出:
2
18



#include <stdio.h>
#include <vector>
#include <string.h>
#include <queue>
using namespace std;
struct Node
{
	int Length;
	int fav;
	int beginTime;
	int endTime;
};
queue<Node> gd;
int k,opTime;
char op[10];

void top(int num)
{
	if(num == 1)
	{
		return;
	}
	queue<Node> temp,temp2;
	int index = 0;
	while(gd.size() && opTime >= gd.front().beginTime)
	{
		temp.push(gd.front());
		gd.pop();
	}
	while(index < num - 1)
	{
		temp2.push(gd.front());
		gd.pop();
		index++;
	}
	Node tempNode = gd.front();
	tempNode.beginTime = temp.back().endTime + 1;
	tempNode.endTime = tempNode.beginTime + tempNode.Length - 1;
	gd.pop();
	index++;
	while(gd.size())
	{
		temp2.push(gd.front());
		gd.pop();
	}
	while(temp.size())
	{
		gd.push(temp.front());
		temp.pop();
	}
	gd.push(tempNode);
	while(temp2.size())
	{
		temp2.front().beginTime = gd.back().endTime + 1;
		temp2.front().endTime = temp2.front().beginTime + temp2.front().Length - 1;
		gd.push(temp2.front());
		temp2.pop();
	}
}

void deleteNode(int num)
{
	queue<Node> temp;
	int index = 0;
	while(gd.size() && opTime >= gd.front().beginTime)
	{
		temp.push(gd.front());
		gd.pop();
	}
	while(index < num - 1)
	{
		temp.push(gd.front());
		gd.pop();
		index++;
	}
	gd.pop();
	while(gd.size())
	{
		if(temp.size())
		{
			gd.front().beginTime = temp.back().endTime + 1;
		}
		else
		{
			gd.front().beginTime = opTime + 1;
		}
		gd.front().endTime = gd.front().beginTime + gd.front().Length - 1;
		temp.push(gd.front());
		gd.pop();
	}
	while(temp.size())
	{
		gd.push(temp.front());
		temp.pop();
	}
}

void cut()
{
	int Index = 0;
	queue<Node> temp;
	while(gd.size() && opTime >= gd.front().beginTime)
	{
		temp.push(gd.front());
		gd.pop();
	}
	temp.back().endTime = opTime;
	while(gd.size())
	{
		if(temp.size())
		{
			gd.front().beginTime = temp.back().endTime + 1;
		}
		else
		{
			gd.front().beginTime = opTime + 1;
		}
		gd.front().endTime = gd.front().beginTime + gd.front().Length - 1;
		temp.push(gd.front());
		gd.pop();
	}
	while(temp.size())
	{
		gd.push(temp.front());
		temp.pop();
	}
}

int main()
{
	while(scanf("%d", &k) != EOF)
	{
		while(gd.size())
		{
			gd.pop();
		}
		int num;
		int curTime = 0;
		for(int i = 0; i < k; i++)
		{
			scanf("%d %s", &opTime, &op);
			if(strcmp(op,"add") == 0)
			{
				Node temp;
				scanf("%d %d", &temp.Length, &temp.fav);
				if(gd.empty())
				{
					temp.beginTime = opTime + 1;
				}
				else if(opTime >= gd.back().endTime)
				{
					temp.beginTime = opTime + 1;
				}
				else
				{
					temp.beginTime = gd.back().endTime + 1;
				}
				temp.endTime = temp.beginTime + temp.Length - 1;
				gd.push(temp);
			}
			else if(strcmp(op,"top") == 0)
			{
				scanf("%d", &num);
				top(num);
			}
			else if(strcmp(op,"delete") == 0)
			{
				scanf("%d", &num);
				deleteNode(num);
			}
			if(strcmp(op,"cut") == 0)
			{
				if(gd.size())
				{
					cut();
				}
			}
		}
		while(gd.size())
		{
			if(gd.front().fav == 1)
			{
				printf("%d\n", gd.front().beginTime);
			}
			gd.pop();
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值