add a1045

This commit is contained in:
Oliver Lew
2021-03-29 01:49:17 +08:00
parent fe92e1bfa3
commit 333f7720e8
2 changed files with 87 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
---
layout: post
date: 2021-03-29 00:23:37 +0800
title: "PAT Advanced 1045. Favorite Color Stripe (30) (C语言实现)"
categories: Advanced
tags: [monotonic sub-list]
permalink: Advanced/1045.html
---
## 题目
{% include_relative html/a1045.md %}
## 思路
{% include_relative analysis/a1045.md %}
## 代码
[Github最新代码](https://github.com/OliverLew/PAT/blob/master/PATAdvanced/1045.c),欢迎交流
```c
{% raw %}#include <stdio.h>
int main()
{
int N, M, L, c, order_to_color[200] = {0}, color_to_order[200] = {0};
int longest_for_color[200] = {0}, longest_before_current, max_length = 0;
/* read number of different colors */
scanf("%d", &N);
/* read color-order pairs (colors start from 0, orders start from 1) */
scanf("%d", &M);
for(int i = M; i > 0; i--)
{
scanf("%d", &c);
order_to_color[i] = --c;
color_to_order[c] = i;
}
/* read color list */
scanf("%d", &L);
for(int i = 0; i < L; i++)
{
scanf("%d", &c);
/* this color is not in the favourite list, do nothing */
if(color_to_order[--c] == 0)
continue;
/* for colors of higher/equal order, find the longest sub-stripe */
longest_before_current = 0;
for(int j = M; j >= color_to_order[c]; j--)
if(longest_before_current < longest_for_color[order_to_color[j]])
longest_before_current = longest_for_color[order_to_color[j]];
/* after this color, the length increases by 1 */
longest_for_color[c] = longest_before_current + 1;
}
for(int i = 0; i < N; i++)
if(max_length < longest_for_color[i])
max_length = longest_for_color[i];
printf("%d\n", max_length);
return 0;
}
{% endraw %}```
+23
View File
@@ -0,0 +1,23 @@
<!--
2021-03-29 00:23:37 +0800
monotonic sub-list
-->
这道题的大意即给出了一组颜色的排序,在一长串颜色中按该顺序选取其中一个子数列。
其实,颜色的数字大小并无意义,如果将所给颜色重新映射为颜色的排名,对于题目的例子,即`2->5, 3->4, 1->3, 5->2, 6->1, 4->0`(不在喜爱颜色里的,如4,就映射为0),那么相当于**在一个数组里找出最长非递减子列**。上面这句话是最重要的,是最重要的,是最重要的。
我比较笨,好长时间都想不出一个快速的方法,终于一天开窍了。这个思路是一遍过的,随时得到目前已读数据的最终解,空间复杂度O(N),时间复杂度O(LN)。
打了很多字,感觉还是说的少一点,更容易理解,所以一句话:
**截至某个元素的最长非递减子列长度,等于它之前截至排名更高的任何颜色(注意不是任何元素)的最长非递减子列长度+1。**
伪代码:
- 读取N和M个喜爱颜色,排序
- 初始化截止于每一个颜色的最长非递减子列长度为0
- 读取L个颜色,对每一个颜色
- 遍历排名高于或等于该颜色的所有颜色,找出子列长度的最大值
- 将该颜色的最长子列长度更新为上述最长长度+1
- 遍历所有颜色,输出子列最长者