常州大學新生寒假訓練會試 大佬的生日大禮包
阿新 • • 發佈:2018-12-31
現在做新生題都很艱難了,為啥其他人都覺得很水,給跪了。
考慮給定3種元素個數
,如何判斷他們能否形成交錯排列。
為了分析方便,設
。首先,將
擺好,那麼最優情況下:
(1)
之間形成的
個間隔可以放置
;
(2)第一個
之前與最後一個
之後可以放置兩段
構成的交錯排列。
也就是說,先在(1)中的區間放置一些可選的排列,使得放滿之後剩餘的
數目滿足
即可。
可以發現,放置
之類消耗相同元素個數的方案不是最優的,因為他們並不會使得
變化,同時也消耗了更多的元素(我們應當儘可能減少元素的消耗防止在某個區間沒有元素可放)。同樣的,放置
也不是最優的。那麼最後的方案就很顯然了,即先依次放置
個
,接著交替放置
和
即可,容易證明這是一定滿足要求的。
故我們可以得到,對於給定元素個數
,如果他們能夠形成交錯排列,則:
。
回到問題,在二分時我們需要判斷:對於給定的
,是否存在
,使得
且他們能夠形成交錯排列。
考慮直接用
進行判斷:
如果
,那麼我們將他們形成的交錯排列取掉
個字首元素或者字尾元素即可;
否則,我們將
減掉
,使得其滿足要求。容易證明此時是最優的情況。那麼如果
,則存在我們需要的交錯排列。
二分即可。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<climits>
#include<random>
using namespace std;
//--Container
//--
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
int ar[3];
bool _cl(int m){
int tr[3]={ar[0]-m,ar[1]-m,ar[2]};
if(tr[0]<0||tr[1]<0||tr[0]+tr[1]+tr[2]<m)return 0;
sort(tr,tr+3);
if(tr[0]>=tr[2]-tr[1]-1)return 1;
if(tr[0]*2+tr[1]*2+1<m)return 0;
return 1;
};
void cl(){
int b,e,m,d;scanf("%d %d %d",&ar[0],&ar[1],&ar[2]);
for(b=0,e=3000000;b<=e;){
m=(b+e)>>1;
if(_cl(m))d=m,b=m+1;
else
e=m-1;
}
printf("%d\n",d);
};
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // ONLINE_JUDGE
int t;scanf("%d",&t);while(t--)cl();
return 0;
};