【CF321E】+【bzoj5311】

时间:2019-08-06
本文章向大家介绍【CF321E】+【bzoj5311】,主要包括【CF321E】+【bzoj5311】使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

决策单调性 + WQS二分

贴个代码先...

//by Judge
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define ll long long
using namespace std;
const int M=4003;
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline ll read(){ ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} int n,K,ans,s[M][M],f[M],w[M];
inline int calc(int j,int i){
    return f[j]+s[i][i]-s[j][i];
}
inline bool judge(int j,int k,int i){ //判断 f[i] 大小 
    int valj=calc(j,i),valk=calc(k,i);
    if(valj^valk) return valj>valk;
    return w[j]>=w[k];
}
inline int rate(int j,int k){  //得到交点位置 
    int l=k+1,r=n;
    while(l<=r){
        int mid=(l+r)>>1;
        if(judge(j,k,mid)) r=mid-1;
        else l=mid+1;
    } return l;
}
inline bool check(int mid){ //二分附加权值 
    static int head,tail,q[M];
    q[head=tail=1]=0;
    fp(i,1,n){ //斜率优化 
        while(head<tail&&judge(q[head],q[head+1],i)) ++head;
        f[i]=calc(q[head],i)+mid,w[i]=w[q[head]]+1;
        while(head<tail&&rate(q[tail-1],q[tail])>rate(q[tail],i)) --tail; q[++tail]=i;
    } return w[n]<=K;
}
int main(){ n=read(),K=read();
    fp(i,1,n) fp(j,1,n) s[i][j]=read();
    fp(i,1,n) fp(j,1,i) s[i][j]=0;
    fp(i,1,n) fp(j,1,n) s[i][j]=s[i][j-1]+s[i][j];
    fp(i,1,n) fp(j,1,n) s[i][j]=s[i-1][j]+s[i][j];
    int l=0,r=s[n][n];
    while(l<=r){ int mid=(l+r)>>1;
        if(check(mid)) r=mid-1,ans=f[n]-K*mid;
        else l=mid+1;
    } return !printf("%d\n",ans);
}

原文地址:https://www.cnblogs.com/Judge/p/11311661.html