• [ZJOI2007]仓库建设


    以前学斜率优化觉得好难

    现在莫名觉得简单 (雾)

    (fee[i])维护的一个前缀和

    (sum[i])维护的成品的前缀和

    (dis[i])维护(0->i)的距离

    易得状态转移方程

    [dp[i] = min(dp[i],dp[j] + fee[i] - fee[j] - sum[j] * (dis[i] - dis[j]) + cost[i]); ]

    时间复杂度 (O(n^2)) (n_{max}=1e6) (TlE)

    考虑优化

    方程中有乘积

    考虑斜率优化

    易得

    [frac{dp[j] - fee[j] + sum[j] * dis[j] - (dp[k] - fee[k] + sum[k] * dis[k])}{(sum[j] - sum[k])}<dis[i] ]

    (Code)

    #include <set>
    #include <stack>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define reg register int
    #define isdigit(x) ('0' <= x&&x <= '9')
    template<typename T>
    inline T Read(T Type)
    {
        T x = 0,f = 1;
        char a = getchar();
        while(!isdigit(a)) {if(a == '-') f = -1;a = getchar();}
        while(isdigit(a)) {x = (x << 1) + (x << 3) + (a ^ '0');a = getchar();}
        return x * f;
    }
    const int MAXN = 1e6 + 10;
    int q[MAXN];
    typedef long long ll;
    ll sum[MAXN],dp[MAXN],dis[MAXN],fee[MAXN],cost[MAXN];
    #define M(x) (x) * (x)
    inline ll Get(int j,int k)
    {
    	return dp[j] - fee[j] + sum[j] * dis[j] - (dp[k] - fee[k] + sum[k] * dis[k]);
    }
    inline ll Get2(int j,int k)
    {
    	return sum[j] - sum[k];
    }
    inline ll Getdp(int i,int j)
    {
    	return dp[j] + fee[i] - fee[j] - sum[j] * (dis[i] - dis[j]) + cost[i];
    }
    int main()
    {
    //	dp[j] - fee[j] - sum[j] * (dis[i] - dis[j]) < 
    //	dp[k] - fee[k] - sum[k] * (dis[i] - dis[k])
    //	dp[j] - fee[j] + sum[j] * dis[j] - (dp[k] - fee[k] + sum[k] * dis[k])  < (sum[j] - sum[k]) * dis[i]
    	int n = Read(1);
        for(reg i = 1;i <= n;i++)
        {
        	int x = Read(1),p = Read(1),c = Read(1);
        	dis[i] = x,sum[i] = sum[i - 1] + p,cost[i] = c;
        	fee[i] = fee[i - 1] + (dis[i] - dis[i - 1]) * sum[i - 1];
    	}
    //	memset(dp,0x3f3f3f,sizeof(dp));
    //	dp[0] = 0;
    //	for(reg i = 1;i <= n;i++)
    //	{
    //		for(reg j = 0;j < i;j++)
    //		{
    //			dp[i] = min(dp[i],dp[j] + fee[i] - fee[j] - sum[j] * (dis[i] - dis[j]) + cost[i]);
    //		}
    //	}
    //	printf("%lld
    ",dp[n]);
        int head = 0,tail = 1;
    	for(reg i = 1;i <= n;i++)
        {
            while(head + 1 < tail&&1.0 * Get(q[head + 1],q[head]) / Get2(q[head + 1],q[head]) <= dis[i])
                head++;
            dp[i] = Getdp(i,q[head]);
            while(head + 1 < tail&&1.0 * Get(i,q[tail - 1]) / Get2(i,q[tail - 1]) <= 1.0 * Get(q[tail - 1],q[tail - 2]) / Get2(q[tail - 1],q[tail - 2]))
                tail--;
            q[tail] = i;
            tail++;
        }
    	printf("%lld
    ",dp[n]);
    	return 0;
    }
    

    (Solution) (II)

    考虑决策单调性

    证明略

  • 相关阅读:
    人们常说的带宽是什么意思?
    关注前端性能
    单测学习笔记
    基于 Istanbul 生成测试用例覆盖率报告
    如何做高水科研
    Human-like Controllable Image Captioning with Verb-specific Semantic Roles(具有动词语义角色的类人可控图像字幕生成)
    Netty应用程序的全部基本构建模块_netty学习笔记(2)-20210405
    异步和事件驱动_netty学习笔记(1)-20210330
    理解 cosocket(转)
    nginx lua阶段处理流程
  • 原文地址:https://www.cnblogs.com/resftlmuttmotw/p/12072608.html
Copyright © 2020-2023  润新知