题意:
就是给你一个数组,这个数组是从原数组查询过来的。怎么个查询法呢,就是q次查询,第i次查询一个区间[l,r],然后让这个区间的值都成为i。问你是否有这样的原数组,如果有就输出。
思考:
这种题一看就是套路题,就是让你找出一点规律,这里明显可以看出来,因为查询的循序不能变,必须是先1再2等等。所以两个相同的数之间不能有比这个数小的数,因为要区间式的覆盖。但是细节很多,值得注意的是,给的数组可能有0,0代表着这个数可以是任意的,所以这里有好多细节。如果最大值不是m,看看是否有0,如果没有0就是错的,如果有0,就让其中一个0为m。然后为0的肯定要和旁边的人一样才是最好的,直接赋值就行。
代码:
struct node{
int L,R;
int minn;
}t[4*N];
int T,n,m;
int va[N];
int vis[N];
map<int,PII > mp;
void build(int node,int l,int r)
{
t[node].L = l,t[node].R = r;
if(l==r)
{
t[node].minn = va[l];
return ;
}
int mid = l+r>>1;
build(node_l,l,mid);
build(node_r,mid+1,r);
t[node].minn = min(t[node_l].minn,t[node_r].minn);
}
int query(int node,int l,int r)
{
if(t[node].R<l||t[node].L>r) return 1e12;
if(t[node].L>=l&&t[node].R<=r) return t[node].minn;
return min(query(node_l,l,r),query(node_r,l,r));
}
signed main()
{
IOS;
cin>>n>>m;
int suc = 1,maxn = 0,res = 0;
for(int i=1;i<=n;i++)
{
cin>>va[i];
if(va[i]==0) res++;
maxn = max(maxn,va[i]);
}
if(maxn!=m&&!res) suc = 0;
if(maxn!=m&&res)
{
for(int i=1;i<=n;i++)
{
if(va[i]!=0) continue;
va[i] = m;
break;
}
}
for(int i=1;i<=n;i++) if(va[i]==0) va[i] = va[i-1];
for(int i=n;i>=1;i--) if(va[i]==0) va[i] = va[i+1];
for(int i=1;i<=n;i++)
{
if(mp[va[i]].fi==0) mp[va[i]].fi = i;
if(mp[va[i]].se==0) mp[va[i]].se = i;
mp[va[i]].fi = min(mp[va[i]].fi,i);
mp[va[i]].se = max(mp[va[i]].se,i);
}
build(1,1,n);
for(auto t:mp)
{
int now = query(1,t.se.fi,t.se.se);
if(now<t.fi) suc = 0;
}
if(!suc) cout<<"NO\n";
else
{
cout<<"YES\n";
if(va[1]==0) for(int i=1;i<=n;i++) va[i] = m;
for(int i=1;i<=n;i++) cout<<va[i]<<" ";
}
return 0;
}
总结:
想想坑点,多多注意细节。