圆邻相异,满足最小
易知如果n个勋章满足,那么n+1+1+....肯定满足
那么我们就要找到最小的满足,二分勋章颜色种数,检查是否满足,从中找到最小的可以满足的勋章数量
这里ma【i】表示第i个将军在与第i-1个将军不冲突的情况下,手中勋章与第1个将军颜色同的最多个数
mi【i】表示第i个将军在与第i-1个将军不冲突的情况下,手中勋章与第1个将军颜色同的最少个数
这样只要mi【n】=0即最后一个将军与第一个将军的勋章颜色的最小个数为0,则这个颜色种数是足够的
mi【i】=a【i】-还能最多提供与第1位将军勋章颜色不同的种数,如果还能最多提供>a【i】,即mi【i】为负数,则mi【i】=0
还能最多提供与第1位将军勋章颜色不同的种数=颜色种数-(a【i-1】+a【1】-ma【i-1】)
那ma【i】=a【1】-mi【i-1】(第1将军中除了i-1用的颜色种类其他全是第i个的),如果后者>a【i】,则为a【i】
#include<bits/stdc++.h> using namespace std; const int Max=3e5+10,N=2e4+10; int ma[N],mi[N],n,a[N],l,r,mid; bool check(int x){ ma[1]=mi[1]=a[1]; for(int i=2;i<=n;i++){ ma[i]=min(a[i],a[1]-mi[i-1]); mi[i]=max(a[i]-(x-(a[i-1]+a[1]-ma[i-1])),0); } return mi[n]==0; } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i],l=max(l,a[i]+a[i-1]); r=Max; while(l<=r){ mid=(l+r)>>1; if(check(mid)) r=mid-1; else l=mid+1; } cout<<l<<endl; return 0; }这里不能像链邻相异,满足最小,求邻之和max是因为头尾可能同
如
3
1 2 1
max邻和=3
但
颜色分部 1,23,1 头尾同色