1. 程式人生 > >[ZJOI2006]trouble 皇帝的煩惱

[ZJOI2006]trouble 皇帝的煩惱

最簡 一行 中國 即將 擁有 string spa 轉移 turn

Description

經過多年的殺戮,秦皇終於統一了中國。為了抵禦外來的侵略,他準備在國土邊境安置n名將軍。不幸的是這n名將軍羽翼漸豐,開始展露他們的狼子野心了。他們拒絕述職、拒絕接受皇帝的聖旨。秦皇已經準備好了秘密處決這些無禮的邊防大將。不過為防兵變,他決定先授予這些將軍一些勛章,為自己贏得戰略時間。將軍們聽說他們即將被授予勛章都很開心,他們紛紛上書表示感謝。第i個將軍要求得到ai枚不同顏色的勛章。但是這些將軍都很傲氣,如果兩個相鄰的將軍擁有顏色相同的勛章他們就會認為皇帝不尊重他們,會立即造反(編號為i的將軍和編號為i+1的將軍相鄰;因為他們駐紮的邊境可以類似看成一個圓形,所以編號1和編號n的將軍也相鄰)。皇帝不得不滿足每個將軍的要求,但對他們的飛揚跋扈感到很氣憤。於是皇帝決定鑄造盡量少種類的勛章來滿足這些狂妄者的要求。請問他至少要鑄造多少種顏色的勛章?

Input

第一行有一個整數n(1<=n<=20000)。接下來n行每行一個整數ai,表示第i個將軍要求得到多少種勛章。(1<=ai<=100000) 輸出一個整數,即最少需要多少種勛章。

Output

4 2 2 1 1

Sample Input

4 本來這只是一道做過但不會做的題,然後今天的省選模擬似乎用到了此題的做法,當然這個模擬題也有可能是我理解錯題意了,於是來寫一篇題解。。。
說是題解,其實也只不過黃學長題解的再解釋罷了,畢竟當初做這個題的時候寫了一個奇怪的模擬,華麗地爆了零。 首先假設最簡單的情況,只要每個人與他一邊的人沒有相同的勛章,於是就能得到一個最大值r,然後在r與2r之間進行二分查找,確定最少勛章數。
b表示每個人最多可以與第一個人有相同種類的勛章,a表示每個人最少可以與第一個人有相同種類的勛章,由b轉移而來 最後檢查一下最後一個人是否可以與第一個人拿完全不一樣的勛章,可以就試試用更少的勛章,否則就要用更多的勛章了
#include<cstdio>
#include<cstring>
using namespace std;
void read(int &y)
{
    y=0;char x=getchar();
    while(x<0||x>9) x=getchar();
    while(x>=0&&x<=
9) { y=y*10+x-0; x=getchar(); } } int min(int x,int y) { return x<y ? x : y; } int max(int x,int y) { return x>y ? x : y; } int t,n,m,ans,v[100001],a[100001],b[100001]; bool pd(int x) { a[1]=b[1]=v[1]; for(int i=2;i<=n;i++) { b[i]=min(v[i],a[1]-a[i-1]); a[i]=max(0,v[1]+v[i]+v[i-1]-b[i-1]-x); } return a[n]==0; } int main() { read(n); for(int i=1;i<=n;i++) { read(v[i]); ans=max(v[i]+v[i-1],ans); } int l=ans,r=ans*2; while(l<=r) { int mid=(l+r)>>1; if(pd(mid)==1) r=mid-1; else l=mid+1; } printf("%d",l); return 0; }

[ZJOI2006]trouble 皇帝的煩惱