把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

2021.7.21 义乌模拟赛 T4 D

这种选\(k\)条的东西一般就是wqs二分。
这道题目显然有凸性,然后就可以二分斜率了。
但是这个输出方案很难搞,按照wqs二分分的方案只有90分因为有斜率相同。
我们考虑对每个点维护两个值\(L\)\(R\)表示最小和最大能选的段数。
这个东西dp的时候稍微处理一下就好了。
然后我们对于每一个点\(i\),如果\(i\)为右端点,那么要满足\(L_i\leq k\leq R_i\),且左端点\(j\)满足\(L_j\leq k-1\leq R_{j}\)
然后就可做了。时间复杂度\(O(nlogn)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db long double
#define N 100000
#define M 20000
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,k,x,y,z,now,g[N+5];ll Sum[N+5],dp[N+5],l,r,mid,A[N+5];
I int check(ll mid){
	re int i,j;now=0;for(i=1;i<=n;i++){
		dp[i]=dp[i-1];g[i]=g[i-1];(dp[now]-Sum[now+1]<dp[i-1]-Sum[i]||(dp[now]-Sum[now+1]==dp[i-1]-Sum[i]&&g[i-1]>g[now]))&&(now=i-1);
		if(dp[now]+Sum[i]-Sum[now+1]+mid>dp[i]||(dp[now]+Sum[i]-Sum[now+1]+mid==dp[i]&&g[now]+1>g[i]))dp[i]=dp[now]+Sum[i]-Sum[now+1]+mid,g[i]=g[now]+1;
	}return g[n]>=k;
}
struct Solve2{
	int las,L[N+5],R[N+5],op,Ansl[N+5],Ansr[N+5],now1,now2,cnt;
	I void calc(int mid){
		re int i;for(i=1;i<=n;i++){
    		dp[i]=dp[i-1];L[i]=L[i-1];R[i]=R[i-1];
			(dp[now1]-Sum[now1+1]<dp[i-1]-Sum[i]||(dp[now1]-Sum[now1+1]==dp[i-1]-Sum[i]&&L[i-1]<L[now1]))&&(now1=i-1);
			(dp[now2]-Sum[now2+1]<dp[i-1]-Sum[i]||(dp[now2]-Sum[now2+1]==dp[i-1]-Sum[i]&&R[i-1]>R[now2]))&&(now2=i-1);
    		(dp[now1]+Sum[i]-Sum[now1+1]+mid>dp[i]||(dp[now1]+Sum[i]-Sum[now1+1]+mid==dp[i]&&L[now1]+1<L[i]))&&(L[i]=L[now1]+1);
    		(dp[now2]+Sum[i]-Sum[now2+1]+mid>dp[i]||(dp[now2]+Sum[i]-Sum[now2+1]+mid==dp[i]&&R[now2]+1>R[i]))&&(R[i]=R[now2]+1);
			dp[i]=max(dp[now1]+Sum[i]-Sum[now1+1]+mid,dp[i]);
    	}
    	for(i=n;i;i--){
    		if(!op){
    			if(L[i]<=k&&R[i]>=k&&((dp[i]==dp[Ansl[cnt]-1]||!cnt)&&(dp[i]^dp[i-1]||L[i-1]>k||R[i-1]<k)))Ansr[++cnt]=i,op=1;
			}if(op){
				if(L[i-1]<=k-1&&R[i-1]>=k-1&&(dp[i-1]+Sum[Ansr[cnt]]-Sum[i]+mid==dp[Ansr[cnt]])) Ansl[cnt]=i,op=0,k--;
			}
		}for(i=1;i<=cnt;i++) printf("%d %d\n",Ansl[i],Ansr[i]);
	}
}S;
int main(){
 	freopen("d.in","r",stdin);freopen("d.out","w",stdout);
	re int i;scanf("%d%d",&n,&k);for(i=2;i<=n;i++) scanf("%lld",&A[i]),Sum[i]=Sum[i-1]+A[i];
	l=-1e10+7;r=1e10+7;while(l+1<r) mid=l+r>>1,(check(mid)?r:l)=mid;check(r);printf("%lld\n",dp[n]-r*k);S.calc(r);
}
posted @ 2021-07-22 21:35  275307894a  阅读(37)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end