1. 程式人生 > 實用技巧 >hdu 6860 Fluctuation Limit 雙向貪心

hdu 6860 Fluctuation Limit 雙向貪心

題意:

給你n個區間[li,ri],和一個整數k,你從每一個區間內選出來一個數,把從第i個區間內選出來數放在第i個位置,這樣會構成一個長度為n的序列,你需要保證序列中任意兩個相鄰的數之差的絕對值要小於等於k

如果這樣的序列存在就輸出Yes和序列,否認輸出No

題解:

就是前後兩次貪心就可以了

先說一下從前向後貪心,我們設我們選擇的第i個數就是v[i]

因為前一個數的選擇會影響到後一個數的選擇,所以我們需要進行從前向後貪心

L[i+1]=max(L[i+1],L[i]-k)

R[i+1]=min(R[i+1],R[i]+k)

然後從後到前在進行一邊這樣的貪心,因為後面的數也會影響前面的數

L[i]=max(L[i],L[i+1]-k)

R[i]=min(R[i],R[i+1]+k)

這樣的話會得到一個新的li和ri陣列,我們只需要輸出其中任意一個元素就行

就是如果第一個區間[L[1],R[1]]輸出第L[1],那麼第二個區間也就輸出L[2]

不要第一個區間輸出L[1],第二個區間輸出R[2],要輸出就輸出對等位置的元素

程式碼:

#include<stack>
#include<queue>
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include
<algorithm> #define fi first #define se second using namespace std; typedef long long ll; const int maxn=1e5+10; const int mod=1e9+7; const double eps=1e-8; int a[maxn],b[maxn]; int main() { int t; scanf("%d",&t); while(t--) { int n,k; scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i) { scanf("%d%d",&a[i],&b[i]); } for(int i=2;i<=n;++i) { a[i]=max(a[i-1]-k,a[i]); b[i]=min(b[i-1]+k,b[i]); } for(int i=n-1;i>=1;--i) { a[i]=max(a[i+1]-k,a[i]); b[i]=min(b[i+1]+k,b[i]); } int flag=0; for(int i=1;i<=n;++i) { if(a[i]>b[i]) { flag=1; break; } } if(flag) { printf("NO\n"); } else { printf("YES\n"); for(int i=1;i<=n;++i) if(i==n) printf("%d\n",a[i]); else printf("%d ",a[i]); } } return 0; }