版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/81806997
考场上东拼西凑打补丁才做出来,多次找到hack自己的数据,WA ON pretest6 5发,然后想到最后一个数字必须出现,被之前的数字覆盖也要出现,才A掉。首先想到对于每个出现的数字,记录一蛤这个数字最左边出现的地方L[i]和最右边出现的地方R[i],说明在第i次query的区间至少要包括L[i]到R[i]这段区间,那么我们直接模拟一蛤区间覆盖,看一蛤最后的情况a数组和目标数组to的关系如何。接下来就是对0的处理,WA了好久,考虑到每个询问必须选出区间,如果q没有出现是不行的,必须要找一个位置放q,这种情况判断一下,其他没出现的就无所谓了,可以直接被q给覆盖掉,还有就是最后a数组中如果还有0的地方,那么可以由附近的不是0的数的区间拓展过来,那么正着扫一遍,倒着到一遍就好了。比赛的时候直接拿出线段树的板子搞了一蛤,后面又写了一遍ST表覆盖版本
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<cmath>
#define maxl 200010
#define inf 20000000001
using namespace std;
int n,q;
int L[maxl],R[maxl],to[maxl],a[maxl],f[19][maxl];
long long ans[maxl];
bool flag;
inline void prework()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=q;i++)
L[i]=n+1,R[i]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&to[i]);
if(to[i]>0)
{
L[to[i]]=min(i,L[to[i]]);
R[to[i]]=max(i,R[to[i]]);
}
}
}
inline void mainwork()
{
flag=true;
for(int i=1;i<=q;i++)
{
if(L[i]<=R[i])
{
int l=log2(R[i]-L[i]+1);
f[l][L[i]]=i;f[l][R[i]-(1<<l)+1]=i;
}
}
for(int l=18;l>=1;l--)
for(int i=1;i<=n;i++)
if(f[l][i])
{
f[l-1][i]=max(f[l][i],f[l-1][i]);
f[l-1][i+(1<<(l-1))]=max(f[l-1][i+(1<<(l-1))],f[l][i]);
}
for(int i=1;i<=n;i++)
a[i]=f[0][i];
for(int i=1;i<=n;i++)
if(to[i]>0 && a[i]!=to[i])
{
flag=false;
return;
}
else
ans[i]=a[i];
int num=0;
for(int i=1;i<=n && L[q]>n;i++)
if(to[i]==0)
{
ans[i]=q;L[q]=i;
break;
}
if(L[q]>n)
{
flag=false;
return;
}
for(int i=1;i<=n;i++)
if(ans[i]==0)
{
num=max(ans[i-1],ans[i+1]);
if(num!=0)
ans[i]=num;
}
for(int i=n;i>=1;i--)
if(ans[i]==0)
{
num=max(ans[i-1],ans[i+1]);
if(num!=0)
ans[i]=num;
}
}
inline void print()
{
if(flag)
{
printf("YES\n");
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
}
else
printf("NO");
}
int main()
{
prework();
mainwork();
print();
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#define maxl 200010
#define inf 20000000001
using namespace std;
int n,q;
int L[maxl],R[maxl],to[maxl],a[maxl];
struct node
{
int l,r;
long long sum,tag;
}tree[maxl<<2];
long long ans[maxl];
bool flag;
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
tree[k].tag=inf;
if(l==r)
{
tree[k].sum=0;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
inline void gank(int k)
{
int v;
if(tree[k].l==tree[k].r)
return;
if(tree[k].tag!=inf)
{
v=tree[k].tag;
tree[k<<1].sum=1ll*(tree[k<<1].r-tree[k<<1].l+1)*v;
tree[k<<1|1].sum=1ll*(tree[k<<1|1].r-tree[k<<1|1].l+1)*v;
tree[k<<1].tag=v;tree[k<<1|1].tag=v;
tree[k].tag=inf;
}
}
inline void add(int k,int l,int r,int v)
{
if(tree[k].tag!=inf)
gank(k);
if(tree[k].l==l && tree[k].r==r)
{
tree[k].sum=1ll*(r-l+1)*v;
tree[k].tag=v;
return;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid)
add(k<<1,l,r,v);
else
if(l>mid)
add(k<<1|1,l,r,v);
else
add(k<<1,l,mid,v),add(k<<1|1,mid+1,r,v);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
inline void prework()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=q;i++)
L[i]=n+1,R[i]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&to[i]);
if(to[i]>0)
{
L[to[i]]=min(i,L[to[i]]);
R[to[i]]=max(i,R[to[i]]);
}
}
build(1,1,n);
}
inline void get(int k)
{
if(tree[k].tag!=inf)
gank(k);
if(tree[k].l==tree[k].r)
{
a[tree[k].l]=tree[k].sum;
return;
}
int mid=(tree[k].l+tree[k].r)>>1;
get(k<<1);get(k<<1|1);
}
inline void mainwork()
{
flag=true;
for(int i=1;i<=q;i++)
{
if(L[i]<=R[i])
add(1,L[i],R[i],i);
}
get(1);
for(int i=1;i<=n;i++)
if(to[i]>0 && a[i]!=to[i])
{
flag=false;
return;
}
else
ans[i]=a[i];
int num=0;
for(int i=1;i<=n && L[q]>n;i++)
if(to[i]==0)
{
ans[i]=q;L[q]=i;
break;
}
if(L[q]>n)
{
flag=false;
return;
}
for(int i=1;i<=n;i++)
if(ans[i]==0)
{
num=max(ans[i-1],ans[i+1]);
if(num!=0)
ans[i]=num;
}
for(int i=n;i>=1;i--)
if(ans[i]==0)
{
num=max(ans[i-1],ans[i+1]);
if(num!=0)
ans[i]=num;
}
}
inline void print()
{
if(flag)
{
printf("YES\n");
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
}
else
printf("NO");
}
int main()
{
prework();
mainwork();
print();
return 0;
}