连号区间数(2013年第四届c/c++ b组第10题)
題目描述
標題:連號區間數
小明這些天一直在思考這樣一個奇怪而有趣的問題:
在1~N的某個全排列中有多少個連號區間呢?這里所說的連號區間的定義是:
如果區間[L, R] 里的所有元素(即此排列的第L個到第R個元素)遞增排序后能得到一個長度為R-L+1的“連續”數列,則稱這個區間連號區間。
當N很小的時候,小明可以很快地算出答案,但是當N變大的時候,問題就不是那么簡單了,現在小明需要你的幫助。
輸入格式:
第一行是一個正整數N (1 <= N <= 50000), 表示全排列的規模。
第二行是N個不同的數字Pi(1 <= Pi <= N), 表示這N個數字的某一全排列。
輸出格式:
輸出一個整數,表示不同連號區間的數目。
示例:
用戶輸入:
4
3 2 4 1
程序應輸出:
7
用戶輸入:
5
3 4 2 5 1
程序應輸出:
9
解釋:
第一個用例中,有7個連號區間分別是:[1,1], [1,2], [1,3], [1,4], [2,2], [3,3], [4,4]
第二個用例中,有9個連號區間分別是:[1,1], [1,2], [1,3], [1,4], [1,5], [2,2], [3,3], [4,4], [5,5]
?
解題過程(其實這道題很簡單,請沒思路的朋友耐心
看下去,也可以直接先看最后面的代碼,很短,看完
代碼或許你就懂了)
?
首先考慮時間復雜度:數據規模N<=50000,而我們要解這道題必定要遍
歷所有的子數組,所以時間復雜度最大為N(N-1)/2,大約是12.5億,也
就是N最大時程序要運行12秒(這還是保守估計),因為計算機每秒我
們都認為計算一億次左右,而題目要求要在5秒之內完成,這幾乎不可能
完成的,所以我們猜測實際出題者實際給出的樣例并不太接近50000。
?
?
走不通的動態規劃思路:
一開始解決這道題的思路是“動態規劃”,所以一直在思考較小的區間與包含這個區間的較大區間之間的聯系:
考慮以下樣例:
[3, 4, 2, 5, 1]
顯然對于包含單個元素的子數組來說肯定符合連號區間的定義,即[3],[4],[2],[5],[1]都是連號區間。
那我們來考慮[3,4]是不是連號區間是否與[3],[4]是連號區間有關,這里[3,4]、[3]、[4]恰好都是
連號區間;
再繼續考慮[4,2]是不是連號區間是否與[4]、[2]是連號區間有關,顯然雖然[4]和[2]都是連號區間,
[4,2]并不是連號區間,經過仔細考慮,我找不到任何可以用動態規劃的痕跡,所以轉換了思路。
?
轉換思路,考慮暴力破解?用哪種方法判斷一個子數組是否符合
連號區間開銷最小?
還是考慮[3, 4, 2, 5, 1]這個樣例,我們先把它排個序,這樣看起來直觀些:
[1, 2, 3, 4, 5]
由于數據元素是有序且唯一的(不存在一個數組里面有兩個元素相等),所以我們會驚喜地發現
當一個數組是連號區間時,有:
數組最大值 - 數組最小值 + 1 = 數組元素個數
我們記為: max - min + 1 = len;
證明max - min + 1 = len
假設一個長度為len的數組為A = {a1, a2, a3, ..., an};
我們干脆就假設數組最小元素min = a1,假設
數組最大元素max = an;
那怎樣使得A數組滿足連號區間呢,根據
連號區間的定義,該數組必須要有min + 1, min + 2,...,
max - 1這些數組元素(一共max - min - 1 個數),
這樣就要求數組元素必須有(max - min + 1)
個數(包括最大元素和最小元素)才能滿足連號區間。
而實際上A數組不一定是有max - min + 1個數組元素的,
這種情況下A數組就不滿足連號區間。
舉個栗子
如果你還不明白我在說什么,那應該是我表達能力太差了,
這樣吧,我們舉個栗子:
考慮以下數據
[3, 4, 2, 7, 1]
這個數組最大值為7,最小值為1,那你想一想,如果要讓該數組滿足
連號區間的定義,必然還要有2,? 3,? 4, 5, 6這幾個數組元素才滿足對吧,
即數組元素個數必定是7個元素(包括最大值和最小值)才滿足連號
區間,而[3, 4, 2, 7, 1]實際才有5個元素,這樣明顯[3, 4, 2, 7, 1]就不符合
連號區間的定義。
?
accept代碼
?
#include <cstdio> #include <iostream> using namespace std; int num[50000 + 10];int main() {int count = 0;int N;cin >> N;count += N; //只有一個元素的子數組明顯符合條件 ,一共有N個只有一個元素的子數組 for(int i = 0; i < N; i++){cin >> num[i];}//遍歷所有子數組,如果子數組滿足“最大元素 - 最小元素 + 1 == 數組長度”,則說明滿足連號區間條件,count++。 for(int i = 0; i < N; i++){int min = num[i];int max = num[i];for(int j = i + 1; j < N; j++){if(min > num[j]){min = num[j];}if(max < num[j]){max = num[j];}if(max - min == j - i){count++;}}}cout << count << endl;return 0; }?
?如果哪里總結錯了,希望各位朋友不吝賜教!!!
?
轉載于:https://www.cnblogs.com/linguosen/p/10534627.html
總結
以上是生活随笔為你收集整理的连号区间数(2013年第四届c/c++ b组第10题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 线程的生命周期
- 下一篇: css之为文本添加线性渐变和外描边