zoukankan      html  css  js  c++  java
  • Codeforces 311B Cats Transport 斜率优化dp

    Cats Transport

    出发时间居然能是负的,我服了。。。 卡了我十几次, 我一直以为斜率优化写搓了。

    我们能得出dp方程式 dp[ i ][ j ] = min(dp[ k ][ j - 1 ] + hs[ i ] * (cnt[ i ] - cnt[ j ]) - sum[ i ] + sum[ j ]) k < i

    这个东西显然能斜率优化, 直接搞。

    其实不用离散化直接dp更好写。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    using namespace std;
    
    const int N = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    
    int n, m, p, d[N], hs[N], h[N], t[N], tot;
    LL dp[2][N], cnt[N], sum[N];
    int que[2][N], head[2], rear[2];
    
    int getId(int x) {
        return lower_bound(hs + 1, hs + tot + 1, x) - hs;
    }
    
    double calc(int j, int k, int t) {
        return 1.0 * (dp[t][j] + sum[j] - dp[t][k] - sum[k]) / (cnt[j] - cnt[k]);
    }
    
    int main() {
        scanf("%d%d%d", &n, &m, &p);
        for(int i = 2; i <= n; i++) scanf("%d", &d[i]);
        for(int i = 2; i <= n; i++) d[i] += d[i - 1];
        LL mn = INF;
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &h[i], &t[i]);
            t[i] -= d[h[i]];
            mn = min(mn, 1ll*t[i]);
        }
        for(int i = 1; i <= m; i++) {
            t[i] -= mn;
            hs[++tot] = t[i];
        }
        sort(hs + 1, hs + tot + 1);
        tot = unique(hs + 1, hs + tot + 1) - hs - 1;
        for(int i = 1; i <= m; i++) cnt[getId(t[i])]++;
        for(int i = 1; i <= tot; i++) sum[i] = sum[i - 1] + cnt[i] * hs[i];
        for(int i = 1; i <= tot; i++) cnt[i] += cnt[i - 1];
        int cur = 0, lst = 1;
        for(int j = 1; j <= p; j++) {
            swap(cur, lst);
            memset(dp[cur], INF, sizeof(dp[cur]));
            head[cur] = 1;
            rear[cur] = 0;
            for(int i = j; i <= tot; i++) {
                if(j == 1) {
                    dp[cur][i] = hs[i] * cnt[i] - sum[i];
                }
                else {
                    while(rear[lst]-head[lst]+1 >= 2
                          && calc(que[lst][head[lst]+1], que[lst][head[lst]], lst) < hs[i]) head[lst]++;
                    int who = que[lst][head[lst]];
                    dp[cur][i] = dp[lst][who] + hs[i] * (cnt[i] - cnt[who]) - sum[i] + sum[who];
                }
                while(rear[cur]-head[cur]+1 >= 2 &&
                      calc(que[cur][rear[cur]], que[cur][rear[cur]-1], cur) >
                      calc(i, que[cur][rear[cur]], cur)) rear[cur]--;
                que[cur][++rear[cur]] = i;
            }
        }
        LL ret = INF;
        if(p >= tot) ret = 0;
        else ret = dp[cur][tot];
        printf("%lld
    ", ret);
        return 0;
    }
    
    /*
    */

      

  • 相关阅读:
    linux addr2line 定位so库崩溃位置
    转:关于Android机型适配这件小事儿
    转:android studio 改编译区背景色
    转:ios review推送与执行
    k2pdfopt下载页
    转:让kindle更好的支持pdf
    转:各种文本格式转换的网站
    转: iOS崩溃堆栈符号表使用与用途
    转: 腾讯Bugly干货分享:Android应用性能评测调优
    转: git的图文使用教程(巨详细)
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10409602.html
Copyright © 2011-2022 走看看