一個傻逼題
阿新 • • 發佈:2020-06-29
題目連線
體驗++
我們首先從確定演算法著手
$ n=1e6 $
根據常識,我們可以選擇的有\(O(nlogn) or O(n)\)
同樣根據常識\(O(nlogn)的玩意兒有二分,線段樹等等\)
\(O(n)\)的玩意兒有dp,貪心
\(dp\)我覺得起碼要開二維才行,否則弄不出來的
那麼就只剩下貪心和二分線段樹之類的
首先二分線段樹之類我是實在想不出怎麼做
貪心倒是可以做出來
思路
XBB結束
我們讓他們第一次過去全部出隊
回來的一趟再把他們拉回來再出隊(霧
我們想想
比如一組數
1 2 3 4 5 6
把第i位拉出來放在最後
是不是隻對\(i+1->n\)的排名有影響?
那麼我們就更新...等等!這不就成\(O(n^2)\)
我們需要用聰明的方法來玄學優化這一個更新
明顯,\(i+1->n\)排名均\(--\)
那麼我們用結合律搞一下,不就是減去\(\sum_{j=i+1}^n a(j)嗎\)
那麼加一個字首和優化一波
然後我們再用指標亂搞一下排名
就AC啦~
#include<bits/stdc++.h> #define N 1001001 #define int unsigned long long using namespace std; inline int read( ){ int sum=0,ft=1; char ch=getchar( ); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar( ); if(ch=='-'){ ch=getchar( ); ft=-1; } while(ch>='0'&&ch<='9'){ sum=ch-'0'+(sum<<3)+(sum<<1); ch=getchar( ); } return ft*sum; } inline void print(int k){ if(!k)return; print(k/10); putchar(k%10+'0'); } int sum[N],n,a[N],pre[N],nex[N],last,xu[N]; inline void work(int k){ nex[last]=k; pre[nex[k]]=pre[k]; nex[pre[k]]=nex[k]; nex[k]=0; pre[k]=last; last=k; } signed main( ){ n=read( ); int i,j,ans=0,k; for(i=1;i<=n;i++){ nex[i]=i+1; pre[i]=i-1; k=read( ); sum[i]=k; a[i]=k; ans=ans+k*i; } last=n; nex[n]=0; for(i=n-1;i>=1;i--)sum[i]+=sum[i+1]; for(i=n;i>=1;i--) if((n-i)*a[i]>sum[i+1]){ ans+=(n-i)*a[i]-sum[i+1]; work(i); } print(ans); putchar('\n'); int ci=0,t; for(i=1;i<=n;i++) if(!pre[i]){ t=i; break; } while(t){ xu[++ci]=t; t=nex[t]; } for(i=1;i<=n;i++){ if(a[xu[i]])print(a[xu[i]]); else putchar('0'); putchar(' '); } }