题解:CF1970B2 Exact Neighbours (Medium)

0tAp

2024-06-11 20:18:23

Solution

题目链接:[Exact Neighbours (Medium)](https://www.luogu.com.cn/problem/CF1970B2) ------------ 简单构造和模拟。 思路:根据题意可知一列只能放 $1$ 个房子,因此我们从左向右开始进行构造,因为 $a_1=0$ 因此我们将第一个房屋放在 $(1,1)$ 便于进行后面的处理,考虑接下来的 $j$ 和 $a_j$,如果 $a_j-j+1$ 刚好等于 $0$ ,说明此房屋和 $1$ 号房屋在同一行时,刚好能走到 $1$ 号房,那么我们就将该房屋放在第 $j$ 列,第 $1$ 行,并指向第一个房屋,如果 $a_j-j+1>0$,那么我们只需要将其向上移动即可,即将该房屋放在第 $j$ 列,第 $a_j-j+2$ 行,并让该房屋指向第一个房屋,如果 $a_j-j+1<0$,那么我们就找离他刚好这个距离的房屋即可,即放置在第 $j$ 列,第 $y_{i-a_i}$ 行(这里的 $y$ 指刚好距离所需放置房屋 $a_j$ 的目标房屋的行数)。 按这个操作从左到右构造下去一定能得到一个合法的方案,因为在 $a_i\le n$ 的情况下每个房子都能根据其距离到一个合法的位置,因此每个房子都能有一个合法的位置。 ------------ 代码如下: ```cpp #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define dwn(i,a,b) for(int i=(a);i>=(b);i--) void solve(){ int n; scanf("%d",&n); vector<int>a(n+10),x(n+10),y(n+10),ans(n+10); rep(i,1,n)scanf("%d",&a[i]); if(a[1]){cout<<"NO";return;} x[1]=1,y[1]=1; ans[1]=1; rep(i,2,n){ if(!a[i]){x[i]=i,y[i]=1,ans[i]=i;continue;} int now=a[i]-i+1; if(now==0){x[i]=i,y[i]=1;ans[i]=1;continue;} if(now>0){x[i]=i,y[i]=now+1;ans[i]=1;continue;} else{x[i]=i,y[i]=y[-now+1],ans[i]=-now+1;continue;} } puts("YES"); rep(i,1,n)printf("%d %d\n",x[i],y[i]); rep(i,1,n)printf("%d ",ans[i]);return; } int main() { solve(); return 0; } ```