题解:CF2053F Earnest Matrix Complement
IvanZhang2009 · · 题解
本题最关键的结论是:每一行只会填一种数。考虑用调整法证明,设一行填了两种数,则考虑这两种数在上下两行中的出现次数,如果不一样则显然填一种可以更优;若一样则填一种等价。
于是可以设计最简单的 dp:
我们考虑维护整个 dp 数组的变化。注意到这玩意可以变成三个可以接受的操作:
-
全局加
c_0c_1 。 -
全局对
\max f_{i-1,k} 取\max 。 -
对于所有有值的
co_j ,单点加co_jc_1 。
按顺序做这三个操作,并实时维护
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define all(v) v.begin(),v.end()
#define pb push_back
#define REP(i,b,e) for(int i=(b);i<(int)(e);++i)
#define over(x) {cout<<(x)<<endl;return;}
int n,m,t;
int f[4000005],X,Y,g[1000005],c[1000005];
void Main() {
cin>>n>>m>>t;
vector<vector<int>>a(n, vector<int>(m));
vector<int>cnt(n);
REP(i,0,n){
cnt[i]=0;
vector<int>b;
REP(j,0,m){
int x;cin>>x;
if(x>0)b.pb(x-1);
else ++cnt[i];
}
reverse(all(b));REP(j,0,cnt[i])b.pb(-1);
reverse(all(b));a[i]=b;
}
if(n==1)over(0)
REP(i,0,t)f[i]=0;
int ans=0;
REP(i,0,n-1){
REP(j,cnt[i],m)++f[a[i][j]];
REP(j,cnt[i+1],m)ans+=f[a[i+1][j]];
REP(j,cnt[i],m)--f[a[i][j]];
}
REP(j,cnt[1],m)f[a[1][j]]+=cnt[0];
X=Y=0;int mx=0;
REP(i,0,t)mx=max(mx,f[i]);
REP(i,1,n){
vector<int>T;
REP(j,cnt[i-1],m)T.pb(a[i-1][j]);
if(i<n-1)REP(j,cnt[i+1],m)T.pb(a[i+1][j]);
for(auto j:T)c[j]=0;
for(auto j:T)++c[j];
int co=cnt[i]*cnt[i-1];
X+=co;Y=max(Y+co,mx);mx+=co;
for(auto j:T)if(c[j]){
f[j]=max(X+f[j],Y)+c[j]*cnt[i];
mx=max(mx,f[j]);
f[j]-=X;c[j]=0;
}
}
mx=0;
REP(j,0,t)mx=max(mx,max(f[j]+X,Y));
over(mx+ans)
}
void TC() {
int tc=1;
cin>>tc;
while(tc--){
Main();
cout.flush();
}
}
signed main() {
return cin.tie(0),cout.tie(0),ios::sync_with_stdio(0),TC(),0;
}
/*
1. CLEAR the arrays (ESPECIALLY multitests)
2. DELETE useless output
*/