版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/83279205
现在做新生题都很艰难了,为啥其他人都觉得很水,给跪了。
考虑给定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;
};