zoukankan      html  css  js  c++  java
  • #4718. 管理

    题目描述

    题解

    考虑暴力dp: $f_{i,j}$表示前 $i$ 个分 $j$ 段的最小值,于是 $f_{i,j}=min{f_{k,j-1}+w_{k+1,i}}$

    其实想一下应该会发现上述dp具有决策单调性,于是我们可以分治求出每个 $i$ 的决策点

    效率: $O(nklogn)$

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=1e5+5;
    int n,m,a[N],c[N],p[N];LL f[N][25];
    void solve(int l,int r,int L,int R,int j,LL k){
        if (L==R){
            for (int i=l;i<=r;i++) p[i]=L;return;
        }
        int mid=(l+r)>>1;LL v=k;
        for (int i=l+1;i<=mid;i++)
            v+=c[a[i]],c[a[i]]++;
        LL w=v+f[L][j];p[mid]=L;
        for (int i=L+1;i<=min(R,mid-1);i++){
            c[a[i]]--;v-=c[a[i]];
            if (w>f[i][j]+v) w=f[i][j]+v,p[mid]=i;
        }
        for (int i=min(R,mid-1);i>p[mid];i--)
            v+=c[a[i]],c[a[i]]++;
        v+=c[a[mid+1]];c[a[mid+1]]++;
        if (mid<r) solve(mid+1,r,p[mid],R,j,v);
        for (int i=p[mid];i>L;i--)
            v+=c[a[i]],c[a[i]]++;
        for (int i=mid+1;i>l;i--)
            c[a[i]]--,v-=c[a[i]];
        if (l<mid) solve(l,mid-1,L,p[mid],j,v);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            f[i][1]=f[i-1][1]+c[a[i]];
            c[a[i]]++;
        }
        for (int i=1;i<=n;i++) c[i]=0;
        for (int j=2;j<=m;j++){
            c[a[j]]++;solve(j,n,j-1,n-1,j-1,0);
            c[a[j]]--;LL v=0;
            for (int i=j,l=j-1,r=j-2;i<=n;i++){
                while(r<i) r++,v+=c[a[r]],c[a[r]]++;
                while(l<p[i]+1) c[a[l]]--,v-=c[a[l]],l++;
                f[i][j]=f[p[i]][j-1]+v;
            }
            for (int i=1;i<=n;i++) c[i]=0;
        }
        cout<<f[n][m]<<endl;return 0;
    }
  • 相关阅读:
    洛谷 P1144 最短路计数
    浅谈最短路计数问题
    洛谷 P1608 路径统计
    洛谷 P6863 [RC-03] 上下求索
    浅谈差值DP
    洛谷 P1651 塔
    JDOJ 1222: VIJOS-P1037 搭建双塔
    浅谈常见字符串处理函数
    浅谈各种浮点数运算函数
    洛谷 P6859 蝴蝶与花
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12283426.html
Copyright © 2011-2022 走看看