Always keep a beginner's |

Tobaa

园龄:1年1个月粉丝:1关注:1

[ABC389C] Snake Queue题解

前情

题意:

问题陈述

有一个(蛇)队列。最初,队列是空的。

你会得到 Q 个查询,这些查询应按给出的顺序处理。查询有三种类型:

  • 类型 1 :以 1 l 的形式给出。一条长度为 l 的蛇会被添加到队列的末尾。如果添加前队列为空,则新添加的蛇的头部位置为 0 ;否则,它就是队列中最后一条蛇的头部坐标与最后一条蛇的长度之和。
  • 类型 2 :以 "2 "的形式给出。队列最前面的蛇离开队列。保证此时队列不是空的。假设 m 是离开队列的蛇的长度,那么队列中剩余的每条蛇的头部坐标都会减少 m
  • 类型 3 :以 3 k 的形式给出。输出距离队列前列 k 的蛇头坐标。保证此时队列中至少有 k 条蛇。

思路

类型 1 和类型 2 做起来都很简单,因为是头部删除尾部入队,首选 deque 来处理,时间复杂度均为 O(1) ,但如果类型 3 用循环一遍进行减去更新的话最坏时间复杂度为 O(N) ,整体时间复杂度为 O(N2) ,在 1Q3×105 的情况下,通过是不现实的。

优化

可以设置一个偏移量进行记录全体蛇的位移情况,每当删除头蛇时,偏移量就加上头蛇的长度,到查询时直接用第 k 条蛇的蛇头坐标减去偏移量即可,这样使时间复杂度优化到 O(N)

注意事项

需要注意的是,偏移量只有在删除蛇时才会改变,因为删除蛇会影响剩余蛇的相对头部坐标,而新添加的蛇是基于队列末尾的蛇来计算头部坐标的。还有记得开long long,被这里卡了。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
		
struct Snake{
	int hd,len;
};
deque <Snake> dq;
signed main(){
	int Q;
	cin>>Q;
	int mov=0;//偏移量记录移动
	while(Q--){
		int q;
		cin>>q;
		if(q==1){//插入操作
			int l;
			cin>>l;
			int nh=0;
			if(!dq.empty()){
				nh=dq.back().hd+dq.back().len;//计算头部坐标
			}
			dq.push_back({nh,l});
		}
		if(q==2){//删除
			int er=dq.front().len;
			dq.pop_front();
			mov+=er;//增加偏移量
		}
		if(q==3){
			int k;
			cin>>k;
			cout<<dq[k-1].hd-mov<<endl;//查询
		}
	}
	return 0;
}

完美结束..

本文作者:Tobaa

本文链接:https://www.cnblogs.com/TobyL/p/18679018

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Tobaa  阅读(44)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起