[cf1615G]Maximum Adjacent Pairs

Posted by Hailwood on Fri, 14 Jan 2022 09:13:00 +0100

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 }

 

Topics: CodeForces