题解:P16444 [XJTUPC 2026] Used to be
lizihan250 · · 题解
给定
考察每一列。对于每一段连续的问号,若其某一段与边界连接,或者其两端连接相同数字,则一定可以填充数字使得这一串问号中不存在相邻两行的数字不同。否则,必定存在至少一处相邻两行不同。设这段问号串位于第
考虑将所有区间按右端点排序,然后从左往右找到第一个没有被选用的点,将该点给这个区间。由于本题中所有区间的长度之和不超过
::::success[参考实现]
#include<bits/stdc++.h>
using namespace std;
const int Maxs=1000000;
int T,n,m,k;
int cnt[Maxs+10];
string mp[Maxs+10];
vector<pair<int,int> > nums[Maxs+10];
bitset<Maxs+10> vis;
void solve()
{
k=0;
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>mp[i];
for(int i=0;i+1<n;i++)
cnt[i]=0,vis[i]=false,nums[i].clear();
for(int j=0;j<m;j++)
{
int p=-1,l=-1;
for(int i=0;i+1<n;i++)
{
if(mp[i][j]!='?') l=i;
if(mp[i][j]!='?'&&mp[i+1][j]!='?') {if(mp[i][j]!=mp[i+1][j]) cnt[i]++;}
else if(mp[i][j]!='?'&&mp[i+1][j]=='?') p=i;
else if(mp[i][j]=='?'&&mp[i+1][j]!='?')
{
if(p!=-1&&mp[p][j]!=mp[i+1][j])
{
nums[i].push_back({p,j});
p=-1;
}
else
{
for(int x=p+1;x<=i;x++)
mp[x][j]=mp[i+1][j];
p=-1;
}
}
}
if(l==-1)
{
if(mp[n-1][j]=='?') mp[n-1][j]='0';
for(int i=0;i+1<n;i++)
mp[i][j]=mp[n-1][j];
}
if(p!=-1)
{
for(int i=l+1;i<n;i++)
mp[i][j]=mp[l][j];
}
}
for(int i=0;i+1<n;i++)
{
if(cnt[i]>1)
{
cout<<"No\n";
return;
}
vis[i]=cnt[i];
}
for(int i=0,c;i+1<n;i++)
{
for(pair<int,int> nw:nums[i])
{
c=-1;
for(int j=nw.first;j<=i;j++)
if(!vis[j])
{
vis[j]=true;
c=j;
break;
}
if(c==-1)
{
cout<<"No\n";
return;
}
for(int j=nw.first;j<=c;j++)
mp[j][nw.second]=mp[nw.first][nw.second];
for(int j=c+1;j<=i;j++)
mp[j][nw.second]=mp[nw.first][nw.second]^1;
}
}
cout<<"Yes\n";
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
cout<<mp[i][j];
cout<<"\n";
}
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>T;
while(T--)
solve();
return 0;
}
::::