A. Rooms and Passages【区间问题】

题目链接:https://codeforces.com/gym/102215/problem/A

题目:
There are (n+1) rooms in the dungeon, consequently connected by n passages. The rooms are numbered from 0 to n, and the passages — from 1 to n. The i-th passage connects rooms (i−1) and i.

Every passage is equipped with a security device of one of two types. Security device of the first type checks if a person who walks through the passage has the pass of the certain color, and forbids movement if such pass is invalid. Security device of the second type never forbids movement, but the pass of the certain color becomes invalid after the person walks through.

In the beginning you are located in the room s and have all the passes. For every s from 0 to (n−1) find how many rooms you can walk through in the direction of the room n.

Input
The first line contains an integer n (1≤n≤500000) — the number of passages.

The second line contains n integers ai (1≤|ai|≤n). The number |ai| is a color of the pass which the i-th passage works with. If ai>0, the i-th passage is the first type passage, and if ai<0 — the second type.

Output
Output n integers: answers for every s from 0 to (n−1).

Examples
inputCopy
6
1 -1 -1 1 -1 1
outputCopy
3 2 1 2 1 1
inputCopy
7
2 -1 -2 -3 1 3 2
outputCopy
4 3 3 2 3 2 1

题目大意:

	面前有n+1个房间,n个门,门有两种:正数门需要你拥有对应数字的钥匙才能通过,负数门随便通过,但是会夺走对应数字的钥匙。问分别在0到n-1作为起点,各自走的最远距离。

这是一个区间问题,我的原始想法非常暴力,用used存钥匙的情况,然后从开始遍历,遇到正数,ans[time]=ans[time-1],遇到负数就往后查。

这种无脑往后面推进的做法直接导致了我的代码的长度,复杂度都上升了,虽然做法得证是正确的,但是因为过于复杂难以纠错,在17th个test就卡住了。

然后看了一下别人的代码发现别人是从反向遍历的,而且没有用到used数组,而是使用了一一对应的位置数组:

遇到正数就更新first[a[time]]=time;
遇到负数就查if(first[-a[time]]!=0)right=min(right,first[-a[time]]);

用right表示最远可达的位置,每次遇到负数,而且他的first数组的数字是一个非零数,就更新right的数值。

最后因为right是最远可达位置,我们每次反向遍历中就可以让ans[time]=right-time;

重点在于保证了right切切实实是最远可达的位置。

const int MAXN=5e5+10;
int a[MAXN],first[MAXN],ans[MAXN];
int main()
{
	int n;
	cin>>n;
	int right=n;
	for(int time=0;time<n;time++)cin>>a[time];
	for(int time=n-1;time>=0;time--)
	{
		if(a[time]>0)first[a[time]]=time;
		else
		{
			if(first[-a[time]]!=0)right=min(right,first[-a[time]]);
		}
		ans[time]=right-time;
	}
	for(int time=0;time<n;time++)cout<<ans[time]<<' ';
	cout<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章