题目要求分成4段 即只能砍3刀 而令其中的3部分不含有不牢固的小木棍 所以所有的不牢固的小木棍都应该唯一同一段 而为了优先满足3段和长度最大 应该使包含不牢固的小木棍的那一段长度尽量短 即应该沿着不牢固的小木棍中编号最大和最小的2个小木棍切2刀 剩下的2段或1段 在计算个数
2段(设为a,b)分成3条边时 只能把较长的a边切开,切开后的2部分a1和a2和大于b了 只要在满足 abs(a1-a2)<b即可 由此可推出a1的上下界 就可以O(1)的算出答案
而对于1段分成3条边时 先将其分成2段 通过枚举其中一段的长度 算出另一段 再带入前面的公式即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int maxn=1e6+100;
const int inf=1e9;
ll go(ll a);
ll go2(ll a,ll b)
{
if(a==b) return 0;
if(a>b)swap(a,b);
if(a==0) return go(b);
ll l=(b-a)/2+1;
ll r=b-l;
return max(r-l+1,(ll)0);
}
ll go(ll a)
{
ll ans=0;
for(int i=1;i<a;i++)
{
int j=a-i;
if(i>j)break;
ans+=go2(i,j);
}
return ans;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
ll ans=0;
int maxx=-1,minn=n+1;
for(int i=0;i<m;i++){
int b;
scanf("%d",&b);
maxx=max(maxx,b);
minn=min(minn,b);
}
if(maxx==-1) ans=go(n);
else ans=go2(minn-1,n-maxx);
printf("%lld\n",ans);
}
}