CF1592F Alice and Recoloring
F1
首先因为左下和右上的操作都是可以用两个左上操作做掉的而且一定不会更劣。
所以我们要关心的就是右下的操作。
手玩可以发现一次右下的操作是可以替换四次左上的操作更优,但是两次就可以被左上等代价替换掉,所以只要看有没有四个左上能被一次右下替换掉就好了。
时间复杂度\(O(nm)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 500
#define M 5
#define mod 1000000007
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
using namespace std;
int n,m,Ans,A[N+5][N+5],Q[N+5][N+5],ToT,Fl[N+5][N+5],fl;char C[N+5];
I void clear(int x,int y){for(int i=x;i<=n;i++) for(int j=y;j<=m;j++) A[i][j]=0;}
int main(){
// freopen("1.in","r",stdin);
RI i,j;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) for(scanf("%s",C+1),j=1;j<=m;j++) A[i][j]=(C[j]=='W'?0:1),ToT+=A[i][j];
for(i=n;i;i--){
for(j=m;j;j--){
if(A[i][j]^Q[i][j])Q[i][j]^=1,Ans++,Fl[i][j]=1;//printf("%d %d %d\n",i,j,Ans);
Q[i][j]&&(Q[i-1][j]^=1,Q[i][j-1]^=1,Q[i-1][j-1]^=1);
}
}
if(Fl[n][m]){
for(i=1;i<n&&!fl;i++) for(j=1;j<m;j++) if(Fl[i][m]&&Fl[n][j]&&Fl[i][j]){fl=1;Ans--;break;}
}
printf("%d\n",Ans);
}
F2
这次右下的代价变小了。
两次右下是可以替换六次左上的。
然后发现第一种情况是右下加上一个L型。
第二种是任意两个L型拼凑在一起的。
所以只要算最多有几个L型就好了。
这个二分图最大匹配即可。
时间复杂度\(O(nm)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 500
#define M 5
#define mod 1000000007
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
using namespace std;
int n,m,Ans,A[N+5][N+5],F[N+5][N+5],ToT,Fl[N+5][N+5],S,T,d[N+5<<1],nows[N+5<<1],x;char C[N+5];
struct yyy{int to,w,z;}tmp;struct ljb{int head,h[N+5<<1];yyy f[N*N+5<<1];I void add(int x,int y,int z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}}s;
I void Get(int x,int y,int z){s.add(x,y,z),s.add(y,x,0);}queue<int> Q;
I int bfs(){
RI i;while(!Q.empty()) Q.pop();Q.push(S);Me(d,0x3f);Me(nows,-1);d[S]=0;nows[S]=s.h[S];
while(!Q.empty())for(x=Q.front(),Q.pop(),i=s.h[x];~i;i=tmp.z){
tmp=s.f[i];if(!tmp.w||d[tmp.to]<1e9)continue;d[tmp.to]=d[x]+1;Q.push(tmp.to);nows[tmp.to]=s.h[tmp.to];if(tmp.to==T)return 1;
} return 0;
}
I int dfs(int x,int sum){
if(x==T) return sum;yyy tmp;int i,pus=0,k;for(i=nows[x];~i;i=tmp.z){
tmp=s.f[i];nows[x]=i;if(!tmp.w||d[tmp.to]!=d[x]+1) continue;k=dfs(tmp.to,min(sum,tmp.w));if(!k) d[tmp.to]=1e9;s.f[i].w-=k;s.f[i^1].w+=k;pus+=k;sum-=k;if(!sum) break;
}return pus;
}
int main(){
// freopen("1.in","r",stdin);
Me(s.h,-1);RI i,j;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) for(scanf("%s",C+1),j=1;j<=m;j++) A[i][j]=(C[j]=='W'?0:1);
for(i=n;i;i--){
for(j=m;j;j--){
if(A[i][j]^F[i][j])F[i][j]^=1,Ans++,Fl[i][j]=1;//printf("%d %d %d\n",i,j,Ans);
F[i][j]&&(F[i-1][j]^=1,F[i][j-1]^=1,F[i-1][j-1]^=1);
}
}T=n+m+1;for(i=1;i<n;i++) Fl[i][m]&&(Get(S,i,1),0);for(i=1;i<m;i++) Fl[n][i]&&(Get(i+n,T,1),0);
for(i=1;i<n;i++) for(j=1;j<m;j++) if(Fl[i][m]&&Fl[n][j]&&Fl[i][j])Get(i,j+n,1);
while(bfs()) ToT+=dfs(S,1e9);if(Fl[n][m]&&ToT) ToT--,Ans-=2;printf("%d\n",Ans-ToT/2*2);
}