1. 程式人生 > >UVALive 3177 Beijing Guards

UVALive 3177 Beijing Guards

val stdin def 這一 none span return 感覺 res

題目大意:給定一個環,每個人要得到Needi種物品,相鄰的人之間不能得到相同的,問至少需要幾種。

首先把n=1特判掉。

然後在n為偶數的時候,答案就是max(Needi+Needi+1)(包括(1,n))。

證明:把物品排成一行,只要一個人從左邊開始取,下一個人從右邊開始取,以此類推,保證不會重復。

然後在n為奇數的時候,答案就不好做了。

觀察一下這道題,發現答案滿足可二分性,不如思考一下check怎麽寫。

因為n為奇數時難點就在看n與1是否矛盾上,只要解決了這個問題,一切好說。

不難發現答案下界就是max(Needi+Needi+1)(包括(1,n)),上界開大一點無所謂的。

還是把物品排成一行,第一個人從左邊開始取。

要使第n個人和第1個人盡量不矛盾,不如讓他從最後開始選。

然後n-1就從前面開始選。

一路逆推回來,你會發現:讓2從左邊開始選。

什麽?1不是從左邊開始選的嗎?為什麽2也從左邊開始選呢?

因為我們二分的mid是可以保證(i,i+1)之間一定不矛盾的,所以從2開始做就是為了n號點與1號點的盡量不矛盾。

換句話說,不會轉過圈的都是一定滿足的,所以就是要把它們以一種合適的方式排布,成全n和1這一對。

感覺在下一盤驚天大棋?

至於維護方式,也是比較巧(套)妙(路)的。

有mid個物品,第一個人選了前Need[1]個,我們就把這些物品分成左右,[1,Need[1]]和[Need[1]+1,mid]。

記L[i]和R[i]表示i在左邊/右邊取了多少個。

對於偶數位,由推導,我們盡量從左邊選。

L[i]=min(Need[i],Need[1]-L[i-1]),R[i]=Need[i]-L[i]。

對於奇數位,盡量從右邊選。

R[i]=min(Need[i],(mid-Need[1])-R[i-1]),L[i]=Need[i]-R[i]。

最後,因為1把L全部取完了,我們只要看L[n]==0即可。

真是妙。

技術分享
#include    <iostream>
#include    <cstdio>
#include    <cstdlib>
#include    
<algorithm> #include <vector> #include <cstring> #include <queue> #include <complex> #include <stack> #define LL long long int #define dob double #define FILE "3177" using namespace std; const int N = 100010; int n,Ned[N],L[N],R[N]; inline int gi(){ int x=0,res=1;char ch=getchar(); while(ch>9||ch<0){if(ch==-)res*=-1;ch=getchar();} while(ch<=9&&ch>=0)x=x*10+ch-48,ch=getchar(); return x*res; } inline bool check(int mid){ int Lh=Ned[1],Rh=mid-Ned[1]; L[1]=Lh;R[1]=0; for(int i=2;i<=n;++i) if(i&1){ R[i]=min(Ned[i],Rh-R[i-1]); L[i]=Ned[i]-R[i]; } else{ L[i]=min(Ned[i],Lh-L[i-1]); R[i]=Ned[i]-L[i]; } return L[n]==0; } int main() { freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); while(n=gi()){ for(int i=1;i<=n;++i)Ned[i]=gi(); if(n==1){printf("%d\n",Ned[1]);continue;} int Ans=Ned[n]+Ned[1]; for(int i=1;i<n;++i) Ans=max(Ans,Ned[i]+Ned[i+1]); if(n&1){ int l=Ans,r=Ans*2;Ans=r; while(l<=r){ int mid=(l+r)>>1; if(check(mid))r=mid-1,Ans=mid; else l=mid+1; } } printf("%d\n",Ans); } fclose(stdin);fclose(stdout); return 0; }
Beijing Guards

UVALive 3177 Beijing Guards