codeforces D. Levko and Array(二分加dp) 挺好的一個題
阿新 • • 發佈:2019-02-16
Note
In the first sample Levko can change the second and fourth elements and get array: 4, 4, 4, 4, 4.
In the third sample he can get array: 1, 2, 3, 4, 5, 6.
題意: 給你n個數 你最多改變其中的k個數使得 兩個相鄰的數之間的差的絕對值最小。
思路: 二分 答案 (二分任意差的絕對值 看在mid的情況下是否符合情況 如果符合情況 那麼r=mid-1 否則l=mid+1 )
而在判斷的時候就要用到dp dp[i] 表示在不改動a[i] 的情況下 前i個數需要改動的個數。
首先dp[1]=0; 那麼dp[i] = ? 當然取決於前邊的情況 如果到j需要改動dp[j] 個數 那麼對於i 就有dp[i]=dp[j]+ i-j-1 ; 表示(j,i)的數都需要改變(開區間) 而改變的條件就是a[i]和
a[j] 的差值 小於等於(i-j)*mid 而是否符合條件只需要看dp[i]+n-i 是否小於等於k
d程式碼:
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define N 2005 using namespace std; typedef long long ll; const ll inf =1e15; int n,k; ll a[N]; ll dp[N]; int jud(ll num) { memset(dp,inf,sizeof(dp)); dp[1]=0; for(int i=2;i<=n;i++) { dp[i]=i-1; for(int j=1;j<i;j++) { if(abs(a[i]-a[j])<=(i-j)*num) { dp[i]=min(dp[i],dp[j]+i-j-1); } } if(dp[i]+n-i<=k) return 1; } return 0; } int main() { cin>>n>>k; for(int i=1;i<=n;i++) scanf("%lld",&a[i]); ll l ,r,mid; l=0; r=inf; ll ans=0; while(l<=r) { mid=(l+r)>>1; //printf(" mid : %lld\n",mid); if(jud(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%lld\n",ans); return 0; } /* 20 17 -5 -9 11 -7 -17 -8 0 -14 -20 -15 7 -13 0 -3 -14 0 9 -10 6 -19 5 1 -1000000000 1000000000 -1000000000 1000000000 -1000000000 */