1 条题解

  • 0
    @ 2025-8-24 22:19:53

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Telesto
    铃兰我老婆!IAKIOIIAKIOIIAKIOIIAKIOIIAKIOIIAKIOI

    搬运于2025-08-24 22:19:53,当前版本为作者最后更新于2021-04-24 14:28:45,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    接雨雨


    原题

    题意:

    我们有一个宽度为 NN、高度无限的二维空间,以及 NN 个可爱的柱子。(N500)(N\leq500)

    其中第 ii 个柱子宽度为 11,高度为 aia_i,最高不会超过 HH(H50)(H\leq50)

    我们可以在二维空间的底线上以任意顺序顺次放置柱子,注意不能扔掉任何一个柱子

    如果某个格子水平方向两侧都有柱子阻挡,那么此处就会积水。而地图边界最左与最右没有阻挡,不会产生积水。


    重要结论:

    对于某个柱子 x 上方的积水体积,可能产生的所有体积都是合法的。
    

    HINT:

    考虑在不含 x 的局面插入 x 。
    

    HINT2:

    让 x 与某个柱子交换。
    

    证明:

    我们最开始先放最高峰与第二高峰(因为她们俩一定不会在上方产生贡献),然后考虑在一个不含 xx 号柱子的局面插入 xx 号柱子能在其上方增加多少积水体积。

    情况一:我们想让 xx 号柱子上方没有积水

    我们找到在所有高度不大于 xx 号柱子、且上方没有积水的柱子里最低的那一个,设为 yy

    我们再找到 yy 两侧中比 yy 更高的某个上方没有积水的柱子 zz,将 xx 插在 zz 靠近 yy 的这一侧。

    因为我们找到的 yy 是所有高度不大于 xx 号柱子、且上方没有积水的柱子里最低的那一个,因此 zz 高度一定大于等于 xx (不然找到的就该是 zz 了),于是这么插入不会产生新的积水。

    首先在存在 yy 的情况中,因为最高峰的存在我们一定不会找不到 zz

    其次如果不存在 yy ,那就证明所有不被积水覆盖的柱子都比 xx 高,那么我们可以将 xx 放置在最边界,这样也不会产生新的积水。

    因此,在一个不存在 xx 的局面中插入 xx ,一定有存在一种方案使得插入后总贡献不变。

    情况二:设某个比他高的柱子为 yy ,目标是使总贡献增加 (ayax)(a_y-a_x)

    1. 如果在该局面下,yy 并没有被积水覆盖

    除让最高峰作为 yy 的情况外,一定可以插入到 yy 的一侧使得 xx 上方有 (ayax)(a_y-a_x) 体积的积水。

    考虑 yy 两侧的积水高度,一定是要么两侧都比她低,要么是一侧比她低、一侧是自己的高度

    而除了最高峰可以是两侧积水都比她自己低,其他柱子不可能产生这种情况(因为最高峰一定比她更高,如果没被积水覆盖,那她与最高峰之间的积水高度一定是她自己的高度)

    1. 如果在该局面下,yy 被积水覆盖

    那么我们就把 yy 所对应的位置换成 xx,然后将 yy 按照情况一的方式处理。

    假设 yy 的两侧离她最近的、那个较低的、没被积水覆盖的柱子为 zz

    显而易见,yy 上方产生的贡献为 (azay)(a_z-a_y) 。如果我们把 yy 换成 xx 显然不会影响其他柱子上方的积水,产生的新贡献为 (azax)(a_z-a_x),总贡献与之前相比增加了 (azax)(azay)=(ayax)(a_z-a_x)-(a_z-a_y)=(a_y-a_x)

    1. 如果在该局面下,yy 未被插入

    按照从大到小插入的方式就可以规避这种情况。

    先处理 yy ,然后再处理 xx

    因为一个更高的柱子产生贡献不可能依赖于更矮的柱子,所以这种产生贡献的依赖关系图是个有向无环图,并且只会有更低的柱子连向更高的柱子这种边。

    我们按照从大到小的顺序插入就不会导致找不到 yy


    综上,对于某个柱子 xx 上方的积水体积,可能产生的所有体积都是合法的。

    有了这个结论我们就可以开始做了。 对所有柱子与比她高的柱子(除去最高峰)做差,然后进行个背包(注意:对于同一局面,某个柱子只能有一种添加贡献的方法),求出哪些值是可行的。枚举复杂度 O(N2)O(N^2),单次转移 O(NH)O(NH),总复杂度 O(N3H)O(N^3H)。显然有点大,但我们可以通过 bitset 优化背包,最终复杂度 O(N3Hω)O(\frac{N^3H}{ω})


    518B,简单又好写,跑得飞快。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxN=5e2+5,maxH=5e1+5;
    
    int a[maxN];
    bitset<maxN*maxH>dp,tem;
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+n);
        dp[0]=true;
        for(int j=1;j<n;++j)
        {
            for(int st=j+1;st<n;++st)
            {
                tem|=(dp<<(a[st]-a[j]));
            }
            dp|=tem;
        }
        for(int i=0;i<=25000;++i)
        {
            if(dp[i])
            {
                printf("%d ",i);
            }
        }
    }
    
    
    • 1

    信息

    ID
    5365
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者