首先,因为((a+b)^2geq a^2+b^2),所以我们总是希望让(1)更加“集中”。当然,这只是一个抽象的原则,具体决策还得靠DP。
考虑区间DP。
设(dp[i][j])表示对于([idots j])这些列,只考虑被([i,j])完全包含的区间,能达到的最大价值。
转移时,我们枚举一个(kin[i,j]),表示把(1)尽可能集中到第(k)列。设所有跨过(k)且被([i,j])完全包含的区间数量为( ext{cnt}(k))(这里的“区间”,其实就是指每一行的第(k)列所在的区间)。则:
[dp[i][j]=max_{kin[i,j]}{dp[i][k-1]+dp[k+1][k]+ ext{cnt}(k)^2}
]
答案就是(dp[1][m])。
时间复杂度(O(nm^3))。
参考代码:
//problem:CF1372E
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T>inline void ckmax(T& x,T y){x=(y>x?y:x);}
template<typename T>inline void ckmin(T& x,T y){x=(y<x?y:x);}
const int MAXN=100;
const int INF=1e9;
int n,m,st[MAXN+5][MAXN+5],ed[MAXN+5][MAXN+5];
vector<pii> seg[MAXN+5];
int dp[MAXN+5][MAXN+5];
int main() {
cin>>n>>m;
for(int i=1;i<=n;++i){
int sz;cin>>sz;
seg[i].resize(sz);
for(int j=0;j<sz;++j){
cin>>seg[i][j].fi>>seg[i][j].se;
for(int k=seg[i][j].fi;k<=seg[i][j].se;++k){
st[i][k]=seg[i][j].fi;
ed[i][k]=seg[i][j].se;
}
}
}
for(int i=1;i<=m;++i){
for(int j=1;j<=m;++j){
dp[i][j]=-INF;
if(i==j){
int cnt=0;
for(int k=1;k<=n;++k)
cnt+=(st[k][i] == ed[k][i]);
dp[i][j]=cnt*cnt;
}
}
}
for(int len=2;len<=m;++len){
for(int i=1;i+len-1<=m;++i){
int j=i+len-1;
for(int k=i;k<=j;++k){
int cnt=0;
for(int l=1;l<=n;++l)
cnt+=(st[l][k]>=i && ed[l][k]<=j);
ckmax(dp[i][j],(k==i?0:dp[i][k-1])+(k==j?0:dp[k+1][j])+cnt*cnt);
}
}
}
cout<<dp[1][m]<<endl;
return 0;
}