Shortest and Longest LIS CodeForces - 1304D

原题链接

考察:贪心

思路:

        由贪心可得,最长上升子序列要求前面尽可能的小,最短上升子序列要求前面尽可能的大.如果没有<>的限制,那么最长上升子序列是1 2 3 4...n,最短上升子序列是n n-1...1.对于最长上升子序列,每有一个>说明前后需要互换位置,对于最短上升子序列,每有一个<说明前后也需要互换位置.如果是连续的>(<),说明最左端应当在最右端,就是reverse一遍>(<)覆盖范围的数组.

Shortest and Longest LIS CodeForces - 1304D
 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 200010;
 6 int n,a[N],b[N];
 7 char s[N];
 8 void get_A()
 9 {
10     for(int i=n;i>=1;i--) a[n-i+1] = i;
11     for(int i=1;i<n;i++)
12     {
13         int j = i;
14         while(j<n&&s[j]=='<') j++;
15         reverse(a+i,a+j+1);
16         i = j;
17     }
18     for(int i=1;i<=n;i++) printf("%d ",a[i]);
19     printf("\n");
20 }
21 void get_B()
22 {
23     for(int i=1;i<=n;i++) b[i] = i;
24     for(int i=1;i<n;i++)
25     {
26         int j = i;
27         while(j<n&&s[j]=='>') j++;
28         reverse(b+i,b+j+1);
29         i = j;
30     }
31     for(int i=1;i<=n;i++) printf("%d ",b[i]);
32     printf("\n");
33 }
34 int main() 
35 {
36     int T;
37     scanf("%d",&T);
38     while(T--)
39     {
40         scanf("%d%s",&n,s+1);
41         get_A(); 
42         get_B();
43     }
44     return 0;
45 }
解决方案一

        说实话完全没想到怎么构造...我果然菜啊.

这里还有一个神级思路二:

       首先复习二分求最长上升子序列长度.我们可以发现,它为了求出最长的上升子序列,是将该长度下最小的元素放在该一类的末尾.那么我们可以根据<>的顺序构造最长上升子序列,为了序列最长,我们需要将小的数放序列末尾.同理为了序列最短,我们需要将大的数放前面.

       这位大佬的思路GO ,里面很详细了,解释以下为什么那么赋值:最短上升子序列因为下标小的要尽量大,而先push都是最小的.而最长子序列下标小的尽量小,所以从后往前赋值.

Shortest and Longest LIS CodeForces - 1304D
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 200010;
 7 int n,a[N],b[N];
 8 char s[N];
 9 vector<vector<int> > asc,des;
10 void Get_A()
11 {
12     des.push_back(vector<int>());
13     int st = 0,pos = 1,p = n;
14     des.push_back(vector<int>());
15     des[0].push_back(pos);
16     for(int i=1;i<n;i++)
17     {
18         if(s[i]=='<')
19         {
20             des.push_back(vector<int>());
21             des[++st].push_back(++pos);
22         }else
23             des[st=0].push_back(++pos);
24     }
25     for(int i=des.size()-1;i>=0;i++)
26       for(int j=0;j<des[i].size();j++)
27            a[des[i][j]] = p--;
28     for(int i=1;i<=n;i++) printf("%d ",a[i]);
29     printf("\n");
30 }
31 void Get_B()
32 {
33     asc.push_back(vector<int>());
34     int st = 0,pos = 1,p = n;
35     asc[st].push_back(pos);
36     for(int i=1;i<n;i++)
37     {
38         if(s[i]=='>')
39             asc[st].push_back(++pos);
40         else
41         {
42             asc.push_back(vector<int>());
43             asc[++st].push_back(++pos);
44         }
45     }
46     for(int i=asc.size()-1;i>=0;i--)
47       for(int j=0;j<asc[i].size();j++) 
48        b[asc[i][j]] = p--;
49     for(int i=1;i<=n;i++) printf("%d ",b[i]);
50     printf("\n");
51 }
52 int main() 
53 {
54     int T;
55     scanf("%d",&T);
56     while(T--)
57     {
58         scanf("%d%s",&n,s+1);
59         asc.clear();
60         des.clear();
61         Get_A();
62         Get_B();
63     }
64     return 0;
65 }
神级思路二

 

上一篇:LeetCode 14. 最长公共前缀(Longest Common Prefix)


下一篇:LeetCode刷题——3. 无重复字符的最长子串