牛客网2019寒假算法训练营day1_G

链接:https://ac.nowcoder.com/acm/contest/317/G
来源:牛客网

小a的排列
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

小a有一个长度为n的排列。定义一段区间是”萌”的,当且仅当把区间中各个数排序后相邻元素的差为1
现在他想知道包含数x,y的长度最小的”萌”区间的左右端点
也就是说,我们需要找到长度最小的区间[l,r],满足区间[l,r]是萌的,且同时包含数x和数y
如果有多个合法的区间,输出左端点最靠左的方案。

输入描述

第一行三个整数N,x,y,分别表示序列长度,询问的两个数
第二行有n个整数表示序列内的元素,保证输入为一个排列

输出描述

输出两个整数,表示长度最小“萌”区间的左右端点

思路

因为输入是一个排列,所以每个数只会出现一次,先找到x和y的下标L,R,然后找到[L,R]内的最大值和最小值,然后找最小值到最大值这些数的最小下标和最大下标l,r,如果[l,r]包含了[L,R],则代表[l,r]之间可能存在多余的数。
然后继续找大的区间的最大最小值,更新l,r和L,R,直到[l,r]不大于[L,R],这时候的区间就是最小的

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
#define wfor(i,j,k) for(i=j;i<k;++i)
#define mfor(i,j,k) for(i=j;i>=k;--i)
// void read(int &x) {
// char ch = getchar(); x = 0;
// for (; ch < '0' || ch > '9'; ch = getchar());
// for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
// }
const int maxn = 1e5 + 5;
int num[maxn];
int pos[maxn];
int main()
{
std::ios::sync_with_stdio(false);
#ifdef test
freopen("F:\\Desktop\\question\\in.txt", "r", stdin);
#endif
#ifdef ubuntu
freopen("/home/time/debug/debug/in", "r", stdin);
freopen("/home/time/debug/debug/out", "w", stdout);
#endif
int n, x, y;
cin >> n >> x >> y;
int i;
wfor(i, 0, n)
{
cin >> num[i];
pos[num[i]] = i;//记录每个数的下标
}
int L, R;
L = pos[x];
R = pos[y];
if (L > R)swap(L, R);
int minx = 0x7f7f7f7f;
int maxx = -1;
wfor(i, L, R + 1)
{
minx = min(minx, num[i]);//找[L,R]之间的最大最小值
maxx = max(maxx, num[i]);
}
int r = -1, l = 0x7f7f7f7f;
wfor(i, minx, maxx + 1)
{
l = min(l, pos[i]);//找最小值到最大值之间的数的最大最小下标
r = max(r, pos[i]);
}
while (l < L || r > R)//如果[l,r]包含了[L,R],则代表[l,r]之间可能存在多余的数
{
int tmaxx = maxx;
int tminx = minx;
wfor(i, l, L + 1)//更新大区间的最大最小值
{
tmaxx = max(tmaxx, num[i]);
tminx = min(tminx, num[i]);
}
L = l;//让L,R拓展到l,r
wfor(i, R, r + 1)
{
tmaxx = max(tmaxx, num[i]);
tminx = min(tminx, num[i]);
}
R = r;
wfor(i, tminx, minx + 1)
{
l = min(l, pos[i]);//用新的最大最小值更新l,r
r = max(r, pos[i]);
}
wfor(i, maxx, tmaxx + 1)
{
l = min(l, pos[i]);
r = max(r, pos[i]);
}
maxx = tmaxx;
minx = tminx;
}
cout << l + 1 << " " << r + 1 << endl;
return 0;
}

本文标题:牛客网2019寒假算法训练营day1_G

文章作者:

发布时间:2019年01月25日 - 15:01

最后更新:2019年01月25日 - 16:01

原始链接:http://startcraft.cn/post/ccdf5645.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------The End-------------