《2020 Multi-University Training Contest 8》
Fluctuation Limit
寻找可行域的问题。
我们需要做的就是不断去缩小这个区间,来使得最后可以满足正向区间和反向区间。
首先,对于i位置为[L,r]。那么i+1肯定要满足[L-k,r+k]。之外就无解。
对于i+1为[L,r],i肯定要满足[L-k,r+k],所以我们正向查找一次,反向查找一次(保持着最小化最大,最大化最小的思路来缩小区间)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<LL,int> pii; const int N = 1e5+5; const int M = 2e6+5; const LL Mod = 998244353; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } LL L[N],r[N]; int main() { int ca;ca = read(); while(ca--) { int n;LL k;n = read(),k = read(); for(int i = 1;i <= n;++i) L[i] = read(),r[i] = read(); int f = 0; for(int i = 2;i <= n;++i) { L[i] = max(L[i],L[i-1]-k); r[i] = min(r[i],r[i-1]+k); } for(int i = n-1;i >= 1;--i) { L[i] = max(L[i],L[i+1]-k); r[i] = min(r[i],r[i+1]+k); } for(int i = 1;i <= n;++i) if(L[i] > r[i]){f = 1;break;} if(f){printf("NO\n");continue;} printf("YES\n"); for(int i = 1;i <= n;++i) printf("%d%c",L[i],i == n ? '\n' : ' '); } system("pause"); return 0; }