题目描述:有一个长度为n的序列a,有q次操作,第i次选择一个区间,将区间里的数全部改为i,序列a的每个位置至少被改一次。得到最终的序列,然后将序列里的某些位置变成0,输出一种可能的置零之前的最终序列,或无解
线段树维护区间0数,在数i的区间中i的个数+0数要等于区间长,然后即可把区间全置0;注意细节,q得有
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
using namespace std;
int n,q;
struct node
{
int l,r;
int sum;
int lazy;
}tr[200005 * 5];
node up(node rt,node ls,node rs)
{
rt.sum=ls.sum+rs.sum;
return rt;
}
void down(int i)
{
if(tr[i].lazy==1)
{
tr[i].lazy=0;
tr[i*2].sum=(tr[i*2].r-tr[i*2].l+1);
tr[i*2].lazy=1;
tr[i*2+1].sum=(tr[i*2+1].r-tr[i*2+1].l+1);
tr[i*2+1].lazy=1;
}
}
void build(int i,int l,int r)
{
tr[i].l=l;tr[i].r=r;
tr[i].sum=0;tr[i].lazy=0;
if(l!=r)
{
int mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tr[i]=up(tr[i],tr[i*2],tr[i*2+1]);
}
}
void update(int i,int l,int r,int ql,int qr)
{
if(l==ql && r==qr)
{
if(tr[i].sum!=(r-l+1))
{
tr[i].sum=(r-l+1);
tr[i].lazy=1;
}
} else{
down(i);
int mid=(l+r)/2;
if(qr<=mid)
{
update(i*2,l,mid,ql,qr);
}
else if(ql>mid)
{
update(i*2+1,mid+1,r,ql,qr);
}
else
{
update(i*2,l,mid,ql,mid);
update(i*2+1,mid+1,r,mid+1,qr);
}
tr[i]=up(tr[i],tr[i*2],tr[i*2+1]);
}
}
node query(int i,int l,int r,int ql,int qr)
{
if(l==ql && r==qr)
{
return tr[i];
}
else
{
down(i);
int mid=(l+r)/2;
if(qr<=mid)
{
return query(i*2,l,mid,ql,qr);
}
else if(ql>mid)
{
return query(i*2+1,mid+1,r,ql,qr);
}
else{
node tr1=query(i*2,l,mid,ql,mid);
node tr2=query(i*2+1,mid+1,r,mid+1,qr);
node ans;
return up(ans,tr1,tr2);
}
}
}
int a[200005];
vector<int> v[200005];
int ans1[200005],ans2[200005];
int main() {
while(~scanf("%d%d",&n,&q))
{
for(int i=0;i<=200000;i++)
v[i].clear(),ans1[i]=ans2[i]=0;
build(1,1,n);
int fq=0,f0=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==q)
fq=i;
if(a[i]==0)
f0=i;
if(a[i]==0)
update(1,1,n,i,i);
else
v[a[i]].push_back(i);
}
if(fq==0)
{
if(f0==0)
{
printf("NO\n");
continue;
} else
{
a[f0]=q;
}
}
int f=0;
for(int i=q;i>=1;i--)
{
if(v[i].size()!=0)
{
int len=v[i].size();
int l=v[i][0],r=v[i][len-1];
node tp=query(1,1,n,l,r);
if((tp.sum+len)==(r-l+1))
{
update(1,1,n,l,r);
ans1[l]=i;ans2[r]=-i;
}
else
f=1;
}
if(f==1)
break;
}
if(f==1)
printf("NO\n");
else
{
printf("YES\n");
stack<int> sta;
for(int i=1;i<=n;i++)
{
if(ans1[i]>0)
sta.push(ans1[i]);
if(a[i]==0)
{
if(sta.size()==0)
a[i]=1;
else
a[i]=sta.top();
}
if(ans2[i]<0)
sta.pop();
printf("%d ",a[i]);
}
printf("\n");
}
}
return 0;
}