思路
从左到右求一遍可行解,再从右到左求一遍可行解。两组解的交集则是全局可行解。输出最小的就是答案。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#define ll long long
using namespace std;
const int maxn=1e5+5;
const int N=5e6+5;
const ll mod=998244353;
ll power(ll x,ll a)
{
ll ans=1;
while(a)
{
if(a&1)
{
ans=ans*x%mod;
}
x=x*x%mod;
a>>=1;
}
return ans;
}
struct st
{
int l,r;
}arr[maxn];
st res1[maxn];
st res2[maxn];
st ans[maxn];
//集合的交运算
st add(st a,st b)
{
st res;
res.l=max(a.l,b.l);
res.r=min(a.r,b.r);
return res;
}
int main()
{
std::ios::sync_with_stdio(false);cin.tie(0);
int t;cin>>t;
while(t--)
{
bool f=1;
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++)
{
cin>>arr[i].l>>arr[i].r;
}
//正可行解
res1[0]=arr[0];
for(int i=1;i<n;i++)
{
st tmp;
tmp.l=res1[i-1].l-k;
tmp.r=res1[i-1].r+k;
res1[i]=add(tmp,arr[i]);
if(res1[i].l>res1[i].r && f)
{
f=0;
break;
}
}
//逆可行解
res2[n-1]=arr[n-1];
for(int i=n-2;i>=0;i--)
{
st tmp;
tmp.l=res2[i+1].l-k;
tmp.r=res2[i+1].r+k;
res2[i]=add(tmp,arr[i]);
if(res2[i].l>res2[i].r && f)
{
f=0;
break;
}
}
//全局可行解
for(int i=0;i<n;i++)
{
ans[i]=add(res1[i],res2[i]);
if(ans[i].l>ans[i].r && f)
{
f=0;
break;
}
}
if(f==0)
{
cout<<"NO\n";
continue;
}
cout<<"YES\n";
for(int i=0;i<n;i++)
{
//cout<<res2[i].l<<' '<<res2[i].r<<endl;;
cout<<ans[i].l<<' ';
}cout<<endl;
}
return 0;
}