Codeforces 1144G Two Merged Sequences

题意:

将一个序列分成两个序列,两个序列中元素的相对顺序保持和原序列不变,使得分出的两个序列一个严格上升,一个严格下降。

思路:

我们考虑每个元素都要进入其中一个序列。

那么我们维护一个上升序列和一个下降序列,对于当前元素$i$:

如果它只能确定的进入一个序列,那么就让它进入。

如果它一个序列也进不去,那么答案就是'NO'。

如果它两个序列都可以进去,那么判断它和后一个元素(如果存在的话)的关系,如果它后一个元素比它大,那么让它进去上升序列,否则进去下降序列。

考虑这样为什么是对的:

首先我们知道一个存在答案的序列里面的元素重复度最大是$2$,那么对于上述的第三种操作,我们考虑一种最特殊的情况,

就是对于第一个元素的判断,它显然可以进入任意一个序列,但是至于让它进入哪个序列,我们不知道。

但是一个比较直观的感觉是,如果它和剩下的数相比相对来说是较大的,我们倾向于让它进入下降序列,反之,进入上升序列

那么其实不用跟剩下的所有数比,只需要让它和后一个数比一下即可。

因为这一步比较,相当于让这个数强行接在后一个数的前面,可以等价于去掉这个数,(做不了选择就不做选择了嘛

但是后一个数跟它相等怎么办?

相等,就两个序列分别进一个呗。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 200010
 5 #define INF 0x3f3f3f3f
 6 int n, arr[N];
 7 vector <int> A, B;
 8 int used[N];
 9 
10 void solve()
11 {
12     A.clear(), B.clear();
13     memset(used, 0, sizeof used); 
14     A.push_back(-1);
15     B.push_back(INF);
16     for (int i = 1; i <= n; ++i)
17     {
18         int x = arr[i], a = A.back(), b = B.back(), y;
19         if (x <= a && x >= b)
20         {
21             puts("NO");
22             return;
23         }
24         else if (x > a && x < b)
25         {
26             if (i == n) 
27                 used[i] = 1;
28             else
29             {
30                 y = arr[i + 1];
31                 if (y > x)
32                     A.push_back(x);
33                 else
34                 {
35                     B.push_back(x);
36                     used[i] = 1;
37                 }
38             }
39         }
40         else if (x > a)
41             A.push_back(x);
42         else
43         {
44             used[i] = 1;
45             B.push_back(x);
46         }
47     }
48     puts("YES");
49     for (int i = 1; i <= n; ++i)
50         printf("%d%c", used[i], " \n"[i == n]);
51 }
52 
53 int main()
54 {
55     while (scanf("%d", &n) != EOF)
56     {
57         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
58         solve();
59     }
60     return 0;
61 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dup4/p/10635933.html