WQS二分求助qwq
查看原帖
WQS二分求助qwq
372708
Yahbim楼主2021/7/9 13:43

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;
}
2021/7/9 13:43
加载中...