1 条题解

  • 0
    @ 2025-8-24 22:01:48

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar bztMinamoto
    **

    搬运于2025-08-24 22:01:47,当前版本为作者最后更新于2018-08-12 13:58:22,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    表示完全看不懂楼下的大佬们说啥……特别是某绿……某c姓大佬

    来说说个人的理解吧

    大佬们说:考虑当前的数xx和之前的最大数yy,(默认x<yx<y,因为如果x>=yx>=y已经满足非降了)为了让它非降,我们要在区间[x,y][x,y]里找到一个数zz,使yy减小到zz,xx增大到zz,那么可以发现,不管取的数是什么,代价都是yxy-x

    不难看出,yy减小的越多,后面的序列越容易变成非降,那么只要让yy减小到xx就好了

    看到这里,我一直有一个疑问,如果令yy减小到xx之后,序列不满足非降了怎么办?

    仔细想了想,实际上应该是这样的:为了让序列非降,yy不能小于yy之前的最大值。而由于yy是整个序列的最大值,如果它之前的最大值zz小于等于xx,那么将yy减小到xx仍能保证序列是非降的。否则的话,zz大于xx小于yy,仍是在区间[x,y][x,y]内,那么移动的代价是yxy-x,所以用于更新答案是没有问题的

    那么这里为什么要让yy减到最小呢?这是因为xxyy不论如何调整,他们的代价之和都已经不变了,但问题是他们目前选的最优方案并不是之后的最优。为了满足他们在之后最优,只有把yy减小到xx,才能保证之后更有可能非降。

    概括一下,对于当前的数,无论最优解如何,对答案的贡献是一定的。而为了保证之后的解也最优,令yy减小到xx,可以保证之后的解最优,且不会影响当前的最优解

    代码好短……

    //minamoto
    #include<cstdio>
    #include<iostream>
    #include<queue>
    using namespace std;
    #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    inline int read(){
        #define num ch-'0'
        char ch;bool flag=0;int res;
        while(!isdigit(ch=getc()))
        (ch=='-')&&(flag=true);
        for(res=num;isdigit(ch=getc());res=res*10+num);
        (flag)&&(res=-res);
        #undef num
        return res;
    }
    priority_queue<int> q;
    int n;long long ans;
    int main(){
    	n=read();
    	while(n--){
    		int x=read();q.push(x);
    		if(x<q.top()){
    			ans+=q.top()-x;
    			q.pop();q.push(x);
    		}
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    
    • 1

    信息

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