码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj5311: 贞鱼

时间:2018-11-02 21:49:20      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:efi   algorithm   freopen   print   nlog   clu   nlogn   而且   main   

还是年轻啊算的时候少乘一个4000被卡二分上界了。。。%%%%bright教我超级快速读D飞bzoj垃圾卡常数据

我们容易写出这样的DP方程:f[i][j]=f[k][j-1]+val(k+1,j)

然后可以发现g(j)是单调减而且是下凸的

那么我们就可以愉快的上wqs二分了

那么f[i]就表示无限分最优解,就有f[i]=f[j]+val(j+1,i)+C

而这个明显是四边形不等式优化的形式

O(nlognlogw)踩了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

const int MAXSIZE=1<<15;
char buf[MAXSIZE],*p1=buf,*p2=buf;
#define gc p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXSIZE,stdin),p1==p2)?EOF:*p1++
int read()
{
    int x=0,f=1;char ch=gc;
    while(ch<0||ch>9){if(ch==-)f=-1;ch=gc;}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=gc;}
    return x*f;
}

int n,s[4100][4100];
int val(int j,int i){return (s[i][i]-s[i][j]-s[j][i]+s[j][j])/2;}
struct node
{
    int l,r,id;
    node(){}
    node(int L,int R,int ID){l=L;r=R;id=ID;}
}q[4100];int f[4100],g[4100];
void check(int C)
{
    int h=1,t=0;q[++t]=node(1,n,0);
    f[0]=0;g[0]=0;
    for(int i=1;i<=n;i++)
    {
        if(q[h].r<i)h++;
        q[h].l=i;
        f[i]=f[q[h].id]+val(q[h].id,i)+C;
        g[i]=g[q[h].id]+1;
        
        if(h>t||f[i]+val(i,n)<=f[q[t].id]+val(q[t].id,n))
        {
            while(h<=t&&f[i]+val(i,q[t].l)<=f[q[t].id]+val(q[t].id,q[t].l))t--;
            if(h>t)q[++t]=node(1,n,i);
            else
            {
                int l=q[t].l,r=q[t].r,ans;
                while(l<=r)
                {
                    int mid=(l+r)/2;
                    if(f[i]+val(i,mid)>f[q[t].id]+val(q[t].id,mid))
                    {
                        ans=mid;
                        l=mid+1;
                    }
                    else r=mid-1;
                }
                q[t].r=ans;
                q[++t]=node(ans+1,n,i);
            }
        }
    }
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int K;
    n=read(),K=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            s[i][j]=read();
            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        }
    
    int l=0,r=(1<<30)-1,ans;
    while(l<=r)
    {
        int mid=(l+r)/2;
        check(mid);
        if(g[n]>=K)
        {
            ans=f[n]-K*mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}

 

bzoj5311: 贞鱼

标签:efi   algorithm   freopen   print   nlog   clu   nlogn   而且   main   

原文地址:https://www.cnblogs.com/AKCqhzdy/p/9898197.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!