【[USACO12MAR]园林绿化Landscaping】

2021-06-22 19:03

阅读:462

标签:getc   还需要   ||   define   push   main   etc   注释   string   

我旁边有一个暴力的金牌爷整天欺负我嘤嘤嘤

关我电脑,关我浏览器,还钦定我学不会贪心

没错我就是学不会了

这道题还是非常妙的

我们发现这个土的数量实在是少的可怜,于是我们甚至可以对每一个单位的土都进行贪心

分成两种情况考虑

  1. 当前的\(a_i,我们还需要往这个位置补一些土,可能是从前面某一个位置拿一些过来,也有可能就是用\(x\)一个单位的代价往这个位置补

  2. \(a_i>b_i\),我们需要去掉一些土,可能是将一些位置的土给拿过来,也有可能就是用\(y\)一个单位的代价往外丢

还有一条非常显然的性质

如果我们想将一些土从\(i\)运到\(j\),那么我们找一个中转点\(k\)(\(i),我们从\(i\)运到\(k\)在运到\(j\),和直接运到\(j\),并没有什么差别

这个非常显然啊,就是利用了这个距离的线性性

之后就可以利用两个堆来贪心了

对于第一种情况,我们利用一个堆来记录前面有哪些位置是土是多出来的,如果我们可以利用多出来的土运到这里使得比加一个价格为\(x\)单位的土更优的话我们就运,否则就直接加上这个\(x\)

如果将前面的运到这里的话,那么对原来的答案也会产生影响,因为能往后运土的点一定是原来土多出来的点,所以还要把原来的那个把土丢掉的花费减掉

所以放进堆里的时候就提前加上那个把土丢掉的花费就好了

之后还有一个地方我就写到注释里吧

#include
#include
#include
#include
#define re register
#define maxn 105
int X,Y,Z;
std::priority_queue q1,q2;
int ans=0,n;
inline int read()
{
    char c=getchar();
    int x=0;
    while(c‘9‘) c=getchar();
    while(c>=‘0‘&&c=X)
                ans+=X,q2.push(i*Z+X);
            else
            {
                int mid=q1.top();
                q1.pop();
                ans+=i*Z-mid;
                q2.push(i*Z*2-mid);
                //这里在上面不好说,干脆就放到注释里说吧
                //首先尽管我们往这里补了一个土,土还是不够的,所以要放进第二个用来存土还没有满的堆
                //之后如果这个位置继续往后传递到一个k位置的话,对答案的贡献应该是(k-pre)*z,也就是i只是一个中转点罢了,所以这里要放上还是要减掉算了两次的i*z
            }
        }
        else
        {
            for(re int j=1;j=Y)
                    ans+=Y,q1.push(i*Z+Y);
            else
            {
                int mid=q2.top();
                q2.pop();
                ans+=i*Z-mid;
                q1.push(i*Z*2-mid);
            }
        }
    }
    std::cout

【[USACO12MAR]园林绿化Landscaping】

标签:getc   还需要   ||   define   push   main   etc   注释   string   

原文地址:https://www.cnblogs.com/asuldb/p/10205732.html


评论


亲,登录后才可以留言!