题解:P10299 [CCC 2024 S5] Chocolate Bar Partition
先把所有的数减去平均值。这样就要求每个连通块的和为
设计 DP。设
转移如下:
每个连通块会在结尾处统计。如果目前和为
由于
时间复杂度 unordered_map 来存
#include<bits/stdc++.h>
using namespace std;
template<class T,class U>
void cmax(T&x,const U&y){if(x<y)x=y;}
using ll=long long;
const int N=200005,inf=1e9;
int n,f[N];
ll sm,t[2][N],s[2][N],sum[N];
unordered_map<ll,int>mp;
int& g(int i,ll j){
if(!mp.count(j-s[0][i]))mp[j-s[0][i]]=-inf;
return mp[j-s[0][i]];
}
int main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n;
for(int i=0;i<2;i++)for(int j=1;j<=n;j++){
cin>>t[i][j];
sm+=t[i][j];
t[i][j]*=n*2;
}
for(int i=0;i<2;i++)for(int j=1;j<=n;j++){
t[i][j]-=sm;
s[i][j]=s[i][j-1]+t[i][j];
}
for(int j=1;j<=n;j++)
sum[j]=s[0][j]+s[1][j];
f[0]=0;
g(0,0)=0;
for(int i=1;i<=n;i++){
cmax(f[i],f[i-1]);//在一起->在一起
cmax(f[i],g(i-1,0));//不在一起->在一起,上面被断开形成连通块
cmax(f[i],g(i-1,sum[i-1]));//不在一起->在一起,下面被断开形成连通块
if(sum[i]==0)f[i]++;//在这里断成一块
//不在一起->不在一起的转移,每次使用偏移量维护
g(i,0)++;//不在一起->不在一起,上面为0了,断成一块
g(i,sum[i])++;//不在一起->不在一起,下面为0了,断成一块
//在一起->不在一起,上面接续
cmax(g(i,sum[i-1]+t[0][i]),f[i-1]+(sum[i-1]+t[0][i]==0)+(sum[i-1]+t[0][i]==sum[i]));
//在一起->不在一起,下面接续,上面分开
cmax(g(i,t[0][i]),f[i-1]+(t[0][i]==0)+(t[0][i]==sum[i]));
}
cout<<max(f[n],g(n,0))<<endl;
return 0;
}