思路
从左到右求一遍可行解,再从右到左求一遍可行解。两组解的交集则是全局可行解。输出最小的就是答案。
代码
#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;
}
本文深入解析了一种用于解决算法竞赛中区间更新与查询问题的有效策略。通过从左至右及从右至左两次求解,寻找全局可行解,并输出最小解作为最终答案。此策略在处理复杂的数据结构和算法挑战时展现出高效性和实用性。
216

被折叠的 条评论
为什么被折叠?



