1. 程式人生 > >洛谷P3929 SAC E#1 - 一道神題 Sequence1【枚舉】

洛谷P3929 SAC E#1 - 一道神題 Sequence1【枚舉】

fin 中一 pla 數列 但是 n) def show clas

題目描述

小強很喜歡數列。有一天,他心血來潮,寫下了一個數列。

阿米巴也很喜歡數列。但是他只喜歡其中一種:波動數列。

一個長度為n的波動數列滿足對於任何i(1 <= i < n),均有:

a[2i-1] <= a[2i] 且 a[2i] >= a[2i+1](若存在) 或者

a[2i-1] >= a[2i] 且 a[2i] <= a[2i+1](若存在)

阿米巴把他的喜好告訴了小強。小強便打算稍作修改,以讓這個數列成為波動數列。他想知道,能否通過僅修改一個數(或不修改),使得原數列變成波動數列。

輸入輸出格式

輸入格式:

輸入包含多組數據。

每組數據包含兩行。

第一行一個整數n表示數列的長度。

接下來一行,n個整數,表示一個數列。

輸出格式:

對於每一組輸入,輸出一行Yes或No,含義如題目所示。

輸入輸出樣例

輸入樣例#1:
5
1 2 3 2 1
5
1 2 3 4 5
輸出樣例#1:
Yes
No

說明

對於30%的數據,n <= 10

對於另外30%的數據,m <= 1000

對於100%的數據,n <= 10^5,m <= 10^9

其中m = max|a[i]|(數列中絕對值的最大值)

【分析】:

如果給定一個序列,可以很容易的在 O(n) 時間內判斷該序 列是否為波動序列。 首先判斷該序列是否為波動序列,如果是,則直接輸 出”Yes“。 否則,枚舉修改哪一個數。 可以發現如一個數要被修改,則將其改為 ∞ 或 −∞ 一定不 會比修改為別的數不優。 所以將其修改為 ∞ 或 −∞ 後再次判斷。 總復雜度 O(n^2)。

AC: 由於波動序列本質上只有 2 種,所以對於每一種波動序列, 求出將原序列變為這種波動序列最少需要修改幾次。

如果兩個值的較小值不大於 1,則輸出”Yes“,否則輸出”No“。

問題變為求原序列變為某種波動序列需要的最小修改次數。 從前向後掃,如果遇到某個元素不滿足要求,則將該元素修 改為 ∞ 和 −∞ 中滿足要求的那個,並將計數器加一。

最後計數器的值就是修改需要的最小次數。 總復雜度 O(n)。

【代碼】:

技術分享
#include <iostream>
#include <cstring>
#include 
<cstdio> #define maxn 100010 using namespace std; int a[maxn]; int n; bool judge(bool dir)// 首先判斷該序列是否為波動序列,如果是,則直接輸 出”Yes“。 否則,枚舉修改哪一個數。 { int cnt = 0; for (int i = 2; i <= n; i++, dir = !dir) if (a[i] != a[i-1] && (a[i] > a[i-1]) != dir) if (++cnt > 1) return false;//從前向後掃,如果遇到某個元素不滿足要求,則將該元素修 改為 ∞ 和 −∞ 中滿足要求的那個,並將計數器加一。 else { i++; dir = !dir; } return true; } int main() { while (scanf("%d", &n) >= 1) { for (int i = 1; i <= n; i++) scanf("%d", &a[i]); if (n <= 3) printf("Yes\n"); else printf(judge(0) || judge(1) ? "Yes\n" : "No\n"); } //如果兩個值的較小值不大於 1,則輸出”Yes“,否則輸出”No“。 return 0; }
View Code

洛谷P3929 SAC E#1 - 一道神題 Sequence1【枚舉】