CF924C Riverside Curio
生活随笔
收集整理的這篇文章主要介紹了
CF924C Riverside Curio
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、題目
點此看題
二、解法
玄學警告?,由于線上的數量是定值,轉而求線的數量已推知線下數量。
設t[i]t[i]t[i]為iii時刻線的數量,d[i]d[i]d[i]為線下的數量,易知 t[i]=m[i]+d[i]+1t[i]=m[i]+d[i]+1t[i]=m[i]+d[i]+1,有這樣一些限制:
- t[i]≥t[i?1]t[i]\geq t[i-1]t[i]≥t[i?1],即線的數量單調遞增
- t[i]≥m[i]t[i]\geq m[i]t[i]≥m[i],這個看定義吧
- t[i]?1≤t[i?1]t[i]-1\leq t[i-1]t[i]?1≤t[i?1],即每天只能畫一條線
前兩個限制取最大值,第三個限制從后往前掃,把t[i]t[i]t[i]和t[i+1]?1t[i+1]-1t[i+1]?1取maxmaxmax,最后掃一遍就可以算出答案,時間復雜度O(n)O(n)O(n)。
那么這個算法的正確性如何推知呢?我的理解是我們盡可能貼著1,21,21,2限制的邊界也就是盡量把線畫重,因為線的數量越少越好,后面我們要掃回來的原因是我們貼著邊界畫不一定畫的出來合法解,我們需要把以前畫重的線拆開,以滿足后面的需要。
#include <cstdio> #include <iostream> #define int long long using namespace std; const int M = 100005; int read() {int x=0,flag=1;char c;while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();return x*flag; } int n,ans,m[M],t[M]; signed main() {n=read();for(int i=1;i<=n;i++)t[i]=max(t[i-1],(m[i]=read())+1);for(int i=n-1;i>=1;i--)if(t[i+1]-1>t[i])t[i]=t[i+1]-1;for(int i=1;i<=n;i++)ans+=t[i]-m[i]-1;printf("%lld\n",ans); }總結
以上是生活随笔為你收集整理的CF924C Riverside Curio的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [经验] PROTEUS仿真学习笔记05
- 下一篇: [动态规划]最长公共子序列