• bzoj5311: 贞鱼


    还是年轻啊算的时候少乘一个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
    ",ans);
        return 0;
    }
  • 相关阅读:
    python 多进程操作
    python 什么是全局解释器锁GIL
    cloudstack api调用python
    cloudstack模板
    微型计算器
    a++与=++a的区别
    js自调用函数的实现方式
    .net利用NPOI导入导出Excel
    linux系统下c程序分多文件实现
    线程的优先级
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9898197.html
Copyright © 2020-2023  润新知