Consider all extremely long zeros, and discuss their length classification——
1. If its length is $2m+1 $, always pair the head / tail with adjacent non-0 elements, and the other elements into $M $pairs
At the same time, if the $k $corresponding to one element in the beginning and end has appeared, it must be paired with another element
2. If its length is $2m $, always match it with $M $pairs, or match the head / tail with adjacent non-0 elements, and the other elements with $m-1 $pairs
At the same time, if the $k $corresponding to an element in the beginning and end has appeared, it must be directly matched into a $m $pair
After dealing with the inevitable situation, you may wish to consider only the choice of the first case——
Connect the leading and trailing adjacent non-0 elements, that is, select an endpoint for each edge and maximize the selected set
Obviously, each connected block is independent. Consider one of the connected blocks:
1. If it is a tree, select any point as the root and select a son for each edge, that is, only the root is not selected
Note that the root is arbitrary, and because the number of sides $< $points, it is impossible to select all points (already optimal)
2. If it is not a tree, select an additional edge after finding the spanning tree, that is, all nodes are selected
Further, consider the selection in combination with the second case (referring to the length of $2m $)——
Similarly, connect the non-0 elements adjacent to the head and tail. For all the edges that select the latter, it is obviously not optimal if they appear twice in the same tree (in case 1)
In other words, reduce all points on the tree in the first case, that is, find the maximum match at this time
There are $o(A) $points and $o(n) $edges in this graph (where $a = \ Max {I = 1} ^ {n} a {I} $), you can directly use the banded tree algorithm
As for the algorithm of banded tree, it is similar to the Hungarian algorithm, and when the odd ring is found in the process of dfs, it will shrink to the point
By adjusting the rotation direction, the augmented path in the new graph can also exist in the original graph (on the contrary, it is obvious), and the correctness is proved
The implementation method is slightly more complex, as follows——
bfs is usually used instead of dfs, and another point is recorded for the point far from the starting point in the (current) unmatched edge on the augmented road
When an odd ring is found, since the scheme needs to be obtained later, the "other point" of the unmatched edge needs to also record the corresponding other point (i.e. record each other)
Let the currently found (unmatched edge) be $(x,y) $, climb the two points up alternately (similar to lca), and climb more than once to get the ring
In addition, for the points on the ring that are expanded directly through the matching edge, the other edges can also be expanded and need to be added to the queue again
The time complexity (I think) is $o (|v|e|) $, which can be passed
The time complexity is $o(An) $, which can be
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define M 605 5 #define fi first 6 #define se second 7 struct Edge{ 8 int nex,to,tp; 9 }edge[N<<1]; 10 pair<int,int>v[N]; 11 queue<int>q; 12 vector<int>bl[M]; 13 int n,m,n0,V,E,x,y,a[N],id[N],visc[N],vis0[N],head[M],vis[M],pos[M],rt[M],fr[M],fa[M],bj[M],pre[M],match[M]; 14 //visc[i]=1 If and only if i Two colors are used(1<=i<M-4) 15 //vis0[i]=1 If and only if i The paragraph has been fully determined 16 void add(int x,int y,int z){ 17 edge[E]=Edge{head[x],y,z}; 18 head[x]=E++; 19 } 20 void dfs1(int k,int fa){ 21 if (pos[k]){ 22 rt[V]=k,fr[V]=fa; 23 return; 24 } 25 pos[k]=V; 26 for(int i=head[k];i!=-1;i=edge[i].nex) 27 if (edge[i].tp!=fa)dfs1(edge[i].to,edge[i].tp); 28 } 29 void dfs2(int k,int fa){ 30 if (vis[k])return; 31 vis[k]=1; 32 if (fa){ 33 vis0[fa]=1; 34 x=v[fa].fi,y=v[fa].se; 35 if (a[x-1]==k){ 36 a[x]=k; 37 for(int i=x+1;i<=y;i+=2)a[i]=a[i+1]=id[n0--]; 38 } 39 else{ 40 a[y]=k; 41 for(int i=x;i<y;i+=2)a[i]=a[i+1]=id[n0--]; 42 } 43 } 44 for(int i=0;i<bl[k].size();i++){ 45 if (vis0[bl[k][i]])continue; 46 x=v[bl[k][i]].fi,y=v[bl[k][i]].se; 47 if ((y-x)&1){ 48 vis0[bl[k][i]]=1; 49 for(int i=x;i<=y;i+=2)a[i]=a[i+1]=id[n0--]; 50 } 51 } 52 for(int i=head[k];i!=-1;i=edge[i].nex) 53 if (edge[i].tp!=fa)dfs2(edge[i].to,edge[i].tp); 54 } 55 int find(int k){ 56 if (k==fa[k])return k; 57 return fa[k]=find(fa[k]); 58 } 59 int lca(int x,int y){ 60 bj[0]++,x=find(x),y=find(y); 61 while (bj[x]!=bj[0]){ 62 bj[x]=bj[0],x=find(pre[match[x]]); 63 if (y)swap(x,y); 64 } 65 return x; 66 } 67 void merge(int k,int lst,int x){ 68 while (find(k)!=x){ 69 pre[k]=lst,lst=match[k]; 70 if (find(k)==k)fa[k]=x; 71 if (find(lst)==lst)fa[lst]=x; 72 if (vis[lst]>0){ 73 vis[lst]=0; 74 q.push(lst); 75 } 76 k=pre[lst]; 77 } 78 } 79 void bfs(int k){ 80 memset(vis,-1,sizeof(vis)); 81 memset(pre,0,sizeof(pre)); 82 for(int i=1;i<=V;i++)fa[i]=i; 83 while (!q.empty())q.pop(); 84 vis[k]=0,q.push(k); 85 while (!q.empty()){ 86 int k=q.front(); 87 q.pop(); 88 for(int i=head[k];i!=-1;i=edge[i].nex){ 89 int x=edge[i].to; 90 if ((find(k)==find(x))||(vis[x]>0))continue; 91 if (vis[x]<0){ 92 vis[x]=1,pre[x]=k; 93 if (!match[x]){ 94 while (x){ 95 int y=pre[x],xx=match[y]; 96 match[x]=y,match[y]=x,x=xx; 97 } 98 return; 99 } 100 vis[match[x]]=0,q.push(match[x]); 101 continue; 102 } 103 int z=lca(k,x); 104 merge(k,x,z),merge(x,k,z); 105 } 106 } 107 } 108 void calc1(){ 109 q.push(0); 110 for(int i=1;i<n;i++) 111 if ((a[i])&&(a[i]==a[i+1]))q.push(a[i]); 112 for(int i=1,j=1;i<=n+1;i++) 113 if ((i>n)||(a[i])){ 114 if (j<i){ 115 v[++m]=make_pair(j,i-1); 116 bl[a[j-1]].push_back(m); 117 bl[a[i]].push_back(m); 118 } 119 j=i+1; 120 } 121 while (!q.empty()){ 122 int k=q.front(); 123 q.pop(); 124 if (k)visc[k]=1; 125 for(int i=0;i<bl[k].size();i++){ 126 if (vis0[bl[k][i]])continue; 127 vis0[bl[k][i]]=1; 128 x=v[bl[k][i]].fi,y=v[bl[k][i]].se; 129 if ((y-x)&1){ 130 for(int i=x;i<=y;i+=2)a[i]=a[i+1]=id[n0--]; 131 } 132 else{ 133 if (a[x-1]!=k){ 134 q.push(a[x-1]),a[x]=a[x-1]; 135 for(int i=x+1;i<=y;i+=2)a[i]=a[i+1]=id[n0--]; 136 } 137 if (a[y+1]!=k){ 138 q.push(a[y+1]),a[y]=a[y+1]; 139 for(int i=x;i<y;i+=2)a[i]=a[i+1]=id[n0--]; 140 } 141 if ((a[x-1]==k)&&(a[y+1]==k)){ 142 a[y]=1; 143 for(int i=x;i<y;i+=2)a[i]=a[i+1]=id[n0--]; 144 } 145 } 146 } 147 bl[k].clear(); 148 } 149 } 150 void calc2(){ 151 E=0; 152 memset(head,-1,sizeof(head)); 153 memset(pos,0,sizeof(pos)); 154 for(int i=1;i<=m;i++) 155 if (!vis0[i]){ 156 x=v[i].fi,y=v[i].se; 157 if ((y-x+1)&1){ 158 add(a[x-1],a[y+1],i); 159 add(a[y+1],a[x-1],i); 160 } 161 } 162 for(int i=1;i<M-4;i++) 163 if ((!visc[i])&&(!pos[i]))V++,dfs1(i,0); 164 E=0; 165 memset(head,-1,sizeof(head)); 166 memset(match,0,sizeof(match)); 167 for(int i=1;i<=m;i++) 168 if (!vis0[i]){ 169 x=v[i].fi,y=v[i].se; 170 if ((rt[pos[a[x-1]]])||(rt[pos[a[y+1]]]))continue; 171 if ((y-x)&1){ 172 x=pos[a[x-1]],y=pos[a[y+1]]; 173 if (x!=y)add(x,y,i),add(y,x,i); 174 } 175 } 176 for(int i=1;i<=V;i++) 177 if (!match[i])bfs(i); 178 for(int i=1;i<=V;i++) 179 if ((match[i])&&(i<match[i])){ 180 for(int j=head[i];j!=-1;j=edge[j].nex) 181 if (edge[j].to==match[i]){ 182 vis0[edge[j].tp]=1; 183 x=v[edge[j].tp].fi,y=v[edge[j].tp].se; 184 a[x]=rt[pos[a[x-1]]]=a[x-1]; 185 a[y]=rt[pos[a[y+1]]]=a[y+1]; 186 for(int k=x+1;k<y;k+=2)a[k]=a[k+1]=id[n0--]; 187 break; 188 } 189 } 190 E=0; 191 memset(head,-1,sizeof(head)); 192 memset(vis,0,sizeof(vis)); 193 for(int i=1;i<=m;i++) 194 if (!vis0[i]){ 195 x=v[i].fi,y=v[i].se; 196 if ((y-x+1)&1){ 197 add(a[x-1],a[y+1],i); 198 add(a[y+1],a[x-1],i); 199 } 200 } 201 for(int i=1;i<M-4;i++) 202 if ((!visc[i])&&(!rt[pos[i]]))rt[pos[i]]=i; 203 for(int i=1;i<=V;i++)dfs2(rt[i],fr[i]); 204 for(int i=1;i<=m;i++) 205 if (!vis0[i]){ 206 x=v[i].fi,y=v[i].se; 207 if ((y-x)&1){ 208 for(int j=x;j<=y;j+=2)a[j]=a[j+1]=id[n0--]; 209 } 210 else{ 211 a[y]=1; 212 for(int j=x;j<y;j+=2)a[j]=a[j+1]=id[n0--]; 213 } 214 } 215 } 216 int main(){ 217 scanf("%d",&n); 218 for(int i=1;i<=n;i++){ 219 scanf("%d",&a[i]); 220 visc[a[i]]=1; 221 } 222 for(int i=1;i<=n;i++) 223 if (!visc[i])id[++n0]=i; 224 memset(visc,0,sizeof(visc)); 225 calc1(),calc2(); 226 for(int i=1;i<=n;i++)printf("%d ",a[i]); 227 return 0; 228 }