1. 程式人生 > >P4597 序列sequence

P4597 序列sequence

www 代碼 stream 如何 mes return etc style span

傳送門

題解

完全看不懂大佬們在說什麽……特別是chen_zhe大佬寫的……

來說說個人的理解吧

大佬們說:考慮當前的數$x$和之前的最大數$y$,(默認$x<y$,因為如果$x>=y$已經滿足非降了)為了讓它非降,我們要在區間$[x,y]$裏找到一個數$z$,使$y$減小到$z$,$x$增大到$z$,那麽可以發現,不管取的數是什麽,代價都是$y-x$

不難看出,$y$減小的越多,後面的序列越容易變成非降,那麽只要讓$y$減小到$x$就好了

看到這裏,我一直有一個疑問,如果令$y$減小到$x$之後,序列不滿足非降了怎麽辦?

仔細想了想,實際上應該是這樣的:為了讓序列非降,$y$不能小於$y$之前的最大值。而由於$y$是整個序列的最大值,如果它之前的最大值$z$小於等於$x$,那麽將$y$減小到$x$仍能保證序列是非降的。否則的話,$z$大於$x$小於$y$,仍是在區間$[x,y]$內,那麽移動的代價是$y-x$,所以用於更新答案是沒有問題的

那麽這裏為什麽要讓$y$減到最小呢?這是因為$x$和$y$不論如何調整,他們的代價之和都已經不變了,但問題是他們目前選的最優方案並不是之後的最優。為了滿足他們在之後最優,只有把$y$減小到$x$,才能保證之後更有可能非降。

概括一下,對於當前的數,無論最優解如何,對答案的貢獻是一定的。而為了保證之後的解也最優,令$y$減小到$x$,可以保證之後的解最優,且不會影響當前的最優解

代碼好短……

 1 //minamoto
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<queue>
 5 using namespace std;
 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 7 char buf[1<<21],*p1=buf,*p2=buf;
 8 inline int
read(){ 9 #define num ch-‘0‘ 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch==-)&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 priority_queue<int> q; 19 int n;long long ans; 20 int main(){ 21 n=read(); 22 while(n--){ 23 int x=read();q.push(x); 24 if(x<q.top()){ 25 ans+=q.top()-x; 26 q.pop();q.push(x); 27 } 28 } 29 printf("%lld\n",ans); 30 return 0; 31 }

P4597 序列sequence