Codeforces Round #544 (Div. 3) dp + 雙指針
阿新 • • 發佈:2019-03-09
題意 移動 deb ace 最大的 ++ bit pac test
int main(){
cin>>n>>k;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
lt[i]=i;
}
sort(a+1,a+n+1);
https://codeforces.com/contest/1133/problem/E
題意
給你n個數(n<=5000),你需要對其挑選並進行分組,總組數不能超過k(k<=5000),每組數字差距不超過5,問最多能挑出多少數字
題解
- 先排序,在進行dp,定義dp[i][j]為前i個數分成j組的最大值
- 兩個轉移方向
- 不選 dp[i-1][j] -> dp[i][j]
- 和前面的分組 dp[lt[i]-1][j-1] -> dp[i][j]
- 怎麽確定i前面的哪個點是最大的?
選擇能和i分到一組的最前面的數
因為選擇最前面的數可以降低前一組的上限
用雙指針or單調隊列處理
雙指針板子
for(l=r=n;l>=1;){
if(l<=r){
if(a[r]-a[l]<=5)
lt[r]=l--;
else lt[--r]=++l; //l++十分重要,因為可能新的l和新的r不合適,這樣就r就會繼續向左移動,原來的r並沒有找到和他合適的l
}else lt[r]=--l;
}
代碼
include<bits/stdc++.h>
define M 5005
using namespace std;
long long a[M],n,k,i,j,p,ans=0,dp[M][M],lt[M],l,r;
cin>>n>>k;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
lt[i]=i;
}
sort(a+1,a+n+1);
for(l=r=n;l>=1;){ if(l<=r){ if(a[r]-a[l]<=5) lt[r]=l--; else lt[--r]=++l; }else lt[r]=--l; } for(i=1;i<=n;i++){ for(j=1;j<=min(k,n);j++){ p=lt[i]; dp[i][j]=max(dp[i-1][j],dp[p-1][j-1]+i-p+1); ans=max(dp[i][j],ans); } } cout<<ans;
}
```
Codeforces Round #544 (Div. 3) dp + 雙指針