TLE/WA了五个点(详情)
WA的直接原因是当l==r时,程序仍未找到种m棵树的方案 (Too Short)
把 while(r>l) 改为 while(r>=l) 后,直接TLE
按WQS二分来说,这种错误是不可能的
求助dalao qwq
CODE:
#include<bits/stdc++.h>
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
const int N=(int)2e5+5;
int n,m,a[N],res[N],pos;
ll ans[N],maxx;
//ans[]:dp数组,记录最大收益;res[]:辅助数组,记录ans[]的植树个数;
//maxx:总最大收益;pos:maxx的植树个数
void dp(bool flag,int k){
for(int i=2;i<n;i++){
if(ans[i-1]>ans[i-2]+a[i]-k) ans[i]=ans[i-1],res[i]=res[i-1];
else if(ans[i-1]<ans[i-2]+a[i]-k) ans[i]=ans[i-2]+a[i]-k,res[i]=res[i-2]+1;
else ans[i]=ans[i-1],res[i]=max(res[i-1],res[i-2]+1);
}//dp转移
if(flag==1){
ans[n]=ans[n-1];
res[n]=res[n-1];
return;
}
if(ans[n-1]>ans[n-2]+a[n]-k) ans[n]=ans[n-1],res[n]=res[n-1];
else if(ans[n-1]<ans[n-2]+a[n]-k) ans[n]=ans[n-2]+a[n]-k,res[n]=res[n-2]+1;
else ans[n]=ans[n-1],res[n]=max(res[n-1],res[n-2]+1);
return;//特判i==n时的情况
}
bool check(int k){
ans[1]=a[1]-k,res[1]=1,ans[0]=res[0]=0;
dp(1,k);
ll pre_ans=ans[n];int pre_res=res[n];
ans[1]=res[1]=ans[0]=res[0]=0;
dp(0,k);//两遍DP处理环形
ll nxt_ans=ans[n];int nxt_res=res[n];
if(pre_ans>nxt_ans){
maxx=pre_ans;
pos=pre_res;
}
else if(pre_ans<nxt_ans){
maxx=nxt_ans;
pos=nxt_res;
}
else maxx=pre_ans,pos=max(pre_res,nxt_res);
//找到总最大收益与此时植树量
return pos>=m;
}
signed main(){
scanf("%d%d",&n,&m);
if(m>n/2){
printf("Error!");
exit(0);
}
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int l=*min_element(a+1,a+1+n),r=*max_element(a+1,a+1+n);
//二分下界与上界
while(r>l){
bool flag=check(mid);
maxx+=pos*mid;
if(flag) l=mid+1;
else r=mid;
if(pos==m){
printf("%lld",maxx);
exit(0);
}//找到了就输出,结束程序
}
return 0;
}