HAOI2006 數字序列 題解

2022-07-08 14:51:15 字數 1516 閱讀 4509

題目鏈結

現在我們有乙個長度為 n的整數序列 a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。

第一行是乙個整數,表示序列長度 n。

第二行有 n個整數,第 i個整數表示序列的第 i項 ai​。

第一行輸出乙個整數,表示最少需要改變多少個數。

第二行輸出乙個整數,表示在改變的數最少的情況下,每個數改變的絕對值之和的最小值。

輸入:4 5 2 3 5

輸出:1 4

第一問題目非常easy

我們發現如果要同時保留a序列中a[i]與a[j]兩個元素,則必須要滿足a[j]-a[i]≥j-i;

移項一下 我們發現 a[j]-j≥a[i]-i;

於是我們發現,我們可以開乙個b陣列其中對於任意元素b[i]=a[i]-i;

顯然 這個b序列一定是不下降的;

於是最少改變多少個數,也就變成了要求b序列的最長不下降子串行,我們可以直接用dp來做複雜度 o(nlogn)

當然 也可以用樹狀陣列來完成這一操作接下來請看第二問

第二問 我們發現一種情況是我們要解決的

每個被保留的b[i]和b[j]之間的均不合法,那麼如何來改變b[i]與b[j]呢?

後面我來給個詳細的證明吧 如果結合我的**思考不出來的話,請看這位大佬的部落格很詳細

就是不斷的縮減所謂的「台階」,最後剩下左邊的高b[i]與右邊的高b[j]

最優解一定是(或者說,一定可以是)左邊的b[i]到b[k]全部變成b[i]並且右邊的b[k+1]到b[j]全部變成b[j]

如果最優解不是這樣,我們可以無償甚至減償來變成這種形態

然後列舉每個區間的k就好了

code:

#includeusing

namespace

std;

#define int long long

#define re register

const

int maxn=4e4+9,inf=0x3f3f3f3f

;int a[maxn],f[maxn],b[maxn],d[maxn],l[maxn],n,len=1

,sum1[maxn],sum2[maxn];

vector

p[maxn];

signed main()

else

}printf(

"%lld\n

",n-len+1

); p[

0].push_back(0

); b[

0]=-inf;b[n+1]=inf;

memset(f,inf,

sizeof

f); f[

0]=0

;

for(re int i=1;i<=n+1;i++)

}printf(

"%lld

",f[n+1

]);

return0;

}

HAOI2006 數字序列

現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。輸入格式 第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。輸出格式 第一行乙個整數表示最少需要改變多少個數。第二行乙個整數,表示在改變的數最少...

HAOI2006 數字序列

現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。輸入格式 第一行包含乙個數n,接下來n個整數按順序描述每一項的鍵值。輸出格式 第一行乙個整數表示最少需要改變多少個數。第二行乙個整數,表示在改變的數最少...

HAOI2006 數字序列 dp,二分

現在我們有乙個長度為n的整數序列a。但是它太不好看了,於是我們希望把它變成乙個單調嚴格上公升的序列。但是不希望改變過多的數,也不希望改變的幅度太大。求在改變的數最少的情況下,每個數改變的絕對值之和的最小值。n leq 35000 保證資料隨機 第一問很容易,只需要令 b i a i i 然後跑最長不...