CF771E Bear and Rectangle Strips
给定一个 \(2 \times n\) 的矩阵 \(T\),你需要选出若干个不相交的子矩阵,要求每个子矩阵中所有数的和为 \(0\)。求子矩阵个数的最大值。
\(1 \leq n \leq 3 \times 10^5\),\(|t_{i,j}| \leq 10^9\)。
首先我们注意到一个结论,有用的子矩阵只有 \(O(n)\) 个,考虑证明。
我们不妨考虑求前缀和,和为 \(0\) 当且仅当两个端点的前缀和相同。
接下来你发现,对于同一个前缀和的值,我们只需要取任意相邻的两个即可。
容易证明这样只会有 \(O(n)\) 个子矩阵。
接下来考虑设计 dp,记 \(d_{i,j}\) 表示第一行填到位置 \(i\),第二行填到位置 \(j\) 的最大子矩形数。
接下来我们转移有三种情况,填第一行的 \([l,r]\),填第二行的 \([l,r]\),以及填两行的 \([l,r]\)。
我们发现为了保持最优解的结构,我们应该选左端点最靠右的矩形,而这是可以预处理的。
接下来你就得到了一个 \(O(n^2)\) 做法,感觉很不牛。
然后加点小优化,记忆化搜索就是对的了。
不知道为啥,很神奇。
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
long long num_1[300010],num_2[300010],sum_1[300010],sum_2[300010],sum_12[300010];
int pos1[300010],pos2[300010],pos12[300010];
map<long long,int> lst_1,lst_2,lst_12;
map<int,int> dp[300010];
int calc(int x,int y){
if(dp[x].find(y)!=dp[x].end()){
return dp[x][y];
}
int maxn=0;
if(x!=y){
maxn=calc(min(x,y),min(x,y));
}
if(pos1[x]>pos2[y] && pos1[x]!=-1){
maxn=max(maxn,calc(pos1[x],y)+1);
}
if(pos1[x]<=pos2[y] && pos2[y]!=-1){
maxn=max(maxn,calc(x,pos2[y])+1);
}
if(x==y && pos12[min(x,y)]!=-1){
maxn=max(maxn,calc(pos12[min(x,y)],pos12[min(x,y)])+1);
}
dp[x][y]=maxn;
return maxn;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&num_1[i]);
sum_1[i]=sum_1[i-1]+num_1[i];
}
for(int i=1;i<=n;i++){
scanf("%lld",&num_2[i]);
sum_2[i]=sum_2[i-1]+num_2[i];
}
for(int i=1;i<=n;i++){
sum_12[i]=sum_12[i-1]+num_1[i]+num_2[i];
}
lst_1[0]=0;
pos1[0]=-1;
int maxn_1=-1;
for(int i=1;i<=n;i++){
if(lst_1.find(sum_1[i])!=lst_1.end()){
maxn_1=max(maxn_1,lst_1[sum_1[i]]);
}
pos1[i]=maxn_1;
lst_1[sum_1[i]]=i;
}
lst_2[0]=0;
pos2[0]=-1;
int maxn_2=-1;
for(int i=1;i<=n;i++){
if(lst_2.find(sum_2[i])!=lst_2.end()){
maxn_2=max(maxn_2,lst_2[sum_2[i]]);
}
pos2[i]=maxn_2;
lst_2[sum_2[i]]=i;
}
lst_12[0]=0;
pos12[0]=-1;
int maxn_12=-1;
for(int i=1;i<=n;i++){
if(lst_12.find(sum_12[i])!=lst_12.end()){
maxn_12=max(maxn_12,lst_12[sum_12[i]]);
}
pos12[i]=maxn_12;
lst_12[sum_12[i]]=i;
}
printf("%d",calc(n,n));
return 0;
}

浙公网安备 33010602011771号