863: [Zjoi2006]trouble 皇帝的煩惱
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 465 Solved: 240
[Submit][Status][Discuss]
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
Sample Output
HINT告訴我是二分?並卵
題解告訴我f[i],g[i]維護與1相同的勳章上界下界?並卵
代碼告訴了我轉移方程?代碼看不懂。
題解:二分一個勳章個數,f[i]表示和1存在相同勳章個數的最小值,g[i]表示最大值
然後查看f[n]是否爲0
爲了報復社會 方程大家自己理解。。。(我的已經好理解很多了,主要是下屆方程較難理解)
1 #include<cstdio> 2 3 #define maxn 100001 4 5 int min(int a,int b){return a<b?a:b;} 6 int max(int a,int b){return a>b?a:b;} 7 8 inline int in() 9 { 10 int x=0;char ch=getchar(); 11 while(ch<'0'||ch>'9')ch=getchar(); 12 while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar(); 13 return x; 14 } 15 16 int a[maxn+1],f[maxn],g[maxn],n; 17 18 bool judge(int ans) 19 { 20 f[1]=a[1];g[1]=a[1]; 21 for(int i=2;i<=n;i++) 22 { 23 if(a[i]+a[i-1]>ans)return 0; 24 f[i]=min(a[1]-g[i-1],a[i]); 25 g[i]=max(0,a[1]-(ans-a[i-1]-(a[i]-f[i-1]))); 26 if(f[i]<g[i])return 0; 27 } 28 return g[n]==0; 29 } 30 31 int main() 32 { 33 int l=1,r=0,ans; 34 n=in(); 35 for(int i=1;i<=n;i++)a[i]=in(),r+=a[i],r=min(r,250000); 36 while(l<=r) 37 { 38 int mid=(l+r)>>1; 39 if(judge(mid))r=mid-1,ans=mid; 40 else l=mid+1; 41 } 42 printf("%d",ans); 43 return 0; 44 }