zoukankan      html  css  js  c++  java
  • #4721. 雕像

    题目描述

    一排 $n$ 个村庄,试规划 $K$ 个雕像的位置(不一定在村庄里),以最小化每个村庄到最近雕像的距离之和。

    题解

    考虑暴力 $ ext{dp}$ : $f[j][i]$ 表示前 $i$ 个分了 $j$ 段的最小值,转移在i这一维满足决策单调性,但是这样是 $O(nklogn)$ 过不去。

    get新知识: $ ext{wqs}$ 二分!

    参考了一些blog总结了一下,一般是题目中要恰好选出 $k$ 个物品的限制,然后如果没有物品个数限制的话对于每个 $x$ ,它的答案为 $f(x)$ , $(x,f(x))$ 是形如一个凸壳的东西的话就可以考虑 $ ext{wqs}$ 二分。可以发现这题答案形式是一个下凸壳。

    我们可以列出 $f[i][j]=f[k-1][j-1]+w(k,i)$ 的 $ ext{dp}$ 形式,那我们可以考虑二分常数 $c$ ,并且用 $w(k,i)+c$ 代替 $w(k,i)$ ,那是不是相当于在那个下凸壳上又加了一条斜率为 $c$ 的直线的新凸壳,如果去掉 $j$ 这一维只剩 $f[i]$ 的话,那求的就是这个新的凸壳的最小值,我们可以通过记录下路径转移来确定最小值的 $x$ ,如果 $x=k$ 的点在最下方的时候那 $y-kc$ 就是我们想要的答案。

    然后 $ ext{dp}$ 的转移部分就是决策单调性,可以写一个单调栈+二分解决。

    效率 $O(n imes logc imes logn)$ 。(oj挂了不知道代码对不对)

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=3e5+5;
    int n,g[N],k;
    LL s[N],f[N],c,A;
    struct O{int l,r,p;}q[N];
    LL F(int j,int i){
        if (j>=i) return 2e18;
        return f[j]+s[i]-s[(i+j)>>1]-s[(i+j+1)>>1]+s[j]+c;
    }
    int J(){
        int u=1,p;q[1]=(O){1,n,0};
        for (int l,r,mid,i=1;i<=n;i++){
            l=1;r=u;p=n+1;
            while(l<r){
                mid=(l+r+1)>>1;
                if (i<q[mid].l) r=mid-1;
                else l=mid;
            }
            f[i]=F(g[i]=q[l].p,i);
            while(u && F(q[u].p,q[u].l)>=F(i,q[u].l)) p=q[u--].l;
            if (u && F(q[u].p,q[u].r)>=F(i,q[u].r)){
                l=q[u].l;r=q[u].r;
                while(l<r){
                    mid=(l+r)>>1;
                    if (F(q[u].p,mid)>=F(i,mid)) r=mid;
                    else l=mid+1;
                }
                p=l;q[u].r=p-1;
            }
            if (p<=n) q[++u]=(O){p,n,i};
        }
        u=0;p=n;
        while(p) p=g[p],u++;
        return u;
    }
    int main(){
        cin>>n>>k;
        for (int i=1;i<=n;i++)
            scanf("%lld",&s[i]),s[i]+=s[i-1];
        LL l=0,r=1e15;
        while(l<=r){
            c=(l+r)>>1;
            if (J()<k) r=c-1;
            else l=c+1,A=f[n]-k*c;
        }
        printf("%lld
    ",A);
        return 0;
    }
  • 相关阅读:
    webservice的两种客户端调用方式(总结)
    Maven笔记
    在myeclipse中建立webservice,发布webservice并且调用webservice接口
    1分钟内使用Adobe Dreamweaver CS5建立导航菜单
    Asp.Net Cookie的清除
    常用的sql标准建表语句
    Java5的 线程并发库
    使用NPOI操作Excel
    使用.net 内置的SmtpClient来实现邮件的发送
    qlikview 地图插件制作教程
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12346708.html
Copyright © 2011-2022 走看看