SDOJ 1195 Zhenhuan
描述
今日又在看甄嬛传,皇上觉得后宫们的勾心斗角太险恶了,有点不好,决定给每个妃子发丝带以让后宫之间和睦相处。皇上一共有N个后宫(标号为1~n),站成一个环形(1号与n号相邻),每个后宫想要ai个丝带,而且这ai个丝带颜色互不相同,而且每个妃子拥有的丝带不能与和她相邻的妃子的丝带有任何一种颜色相同。
皇上不喜欢太多的颜色,所以皇上就像知道最少需要多少种颜色就能满足所有后宫的要求,设最小颜色为M,而甄嬛想提前知道M的值,以告诉皇上来赢得欢心,然而在皇上后宫太多了,她就不会了,所以呢,她向学信息奥赛的你求助,并答应事成之后奖励你
(21,000,000,006mod1,000,000,007)−1(21,000,000,006mod1,000,000,007)−1吨黄金
输入
第一行一个整数n,接下来有n个数字,第i个数字为ai,表示编号为i的后宫想要ai条丝带。
输出
一个整数表示M
样例输入
960
2
465
159
628
110
88
592
193
546
880
400
622
样例输出
1582
数据范围: 40%的数据:n mod 2==0。0<=ai<=1,000,000,000; 100%的数据:n<=20000。0<=ai<=1,000,000,000;
----------------------------------------------------这是一条分界线-------------------------------------------------------
这道题首先想到的是贪心,分类讨论n%2=1和n%2=0的情况(但听说最高调到了90分????)
而实际上这是个二分答案。二分ans,并判定其是否满足
而说到判定,我觉得这个过程又有点像DP.....
【以下受某blog启发】
“
判定答案ans
,即1与n的最小冲突个数是否为0令mi[i]
表示1与i的最小冲突个数,ma[i]
表示1与i的最大冲突个数。
那么有:
1.最多能冲突那么就是全部都冲突了或是分了上一个冲突了的。
2.最小能冲突那么就是一个都不冲突,否则需要知道最多不冲突的个数,由上一个最多冲突的个数求得。
mi[i]=max{ 0,ai-[ans-ai-1-(a1-ma[i-1])] }
那么mi[n]==0就表示当前答案可行
”
于是贴代码~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int n,ans; 8 int ma[20010],mi[20010]; 9 int a[20010]; 10 bool check(int x) 11 { 12 ma[1]=mi[1]=a[1]; 13 for(int i=2;i<=n;i++) 14 { 15 ma[i]=min(a[i],a[1]-mi[i-1]); 16 mi[i]= max( 0, a[i] - ( x-a[i-1]-(a[1]-ma[i-1]) ) ); 17 } 18 return mi[n]; 19 } 20 int main() 21 { 22 scanf("%d",&n); 23 for(int i=1;i<=n;i++) 24 scanf("%d",&a[i]); 25 for(int i=2;i<=n;i++) 26 ans=max(ans,a[i]+a[i-1]); 27 int l=ans,r=ans*2,mid; 28 while(l<=r) 29 { 30 mid=(l+r)>>1; 31 if (check(mid)) l=mid+1; 32 else r=mid-1; 33 } 34 printf("%d",l); 35 return 0; 36 }