题目
思路来源
乱搞ac
题解
由于k不是固定的,所以不用记录k,只需每次往上续上一段即可
容易想到O(n^4)的做法,就是枚举a的最后一段,b的最后一段,
只要这最后一段对应合法,续在前面的合法方案后就可以了
然后考虑怎么优化这个O(n^4),还是dp[i][j]表示第一段以i结尾、第二段以j结尾的合法方案
枚举x<i,枚举y<j,[x,i]区间与[y,j]区间一共是O(n)个的,
可以先预处理它们的平均值的排序,O(n^2logn),
然后对两堆有序的再进行归并排序,这样复杂度就是O(n^3)的了
思想是这个思想,但是注意到,如果直接这样枚举的话,
转移的时候,dp[i][j]要从dp[x-1][y-1]转移过来,这两维都不是固定的,实际无法完成归并
所以,要把第一维固定成i,这样才能对第二维进行归并,
所以,枚举x>i,枚举y<j,对区间[i,x]和区间[y,j]进行归并,
不妨按平均值从大到小归并,这样可以把所有平均值大的dp[i-1][y-1]
加到当前dp[x][j]上,保证了变量同时只会有一维
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=505,mod=1e9+7;
int n,a[N],b[N],sum[N],sum2[N],dp[N][N];
vector<int>p[N],q[N];
void add(int &x,int y){
x=(x+y)%mod;
}
int main(){
sci(n);
rep(i,1,n){
sci(a[i]);
sum[i]=sum[i-1]+a[i];
}
rep(i,1,n){
rep(j,i,n){
p[i].pb(j);
}
sort(p[i].begin(),p[i].end(),[&](int x,int y){
return 1ll*(sum[x]-sum[i-1])*(y-i+1)>1ll*(sum[y]-sum[i-1])*(x-i+1);//[i,x] [i,y]
});
}
rep(i,1,n){
sci(b[i]);
sum2[i]=sum2[i-1]+b[i];
rep(j,0,i-1){
q[i].pb(j);
}
sort(q[i].begin(),q[i].end(),[&](int x,int y){
return 1ll*(sum2[i]-sum2[x])*(i-y)>1ll*(sum2[i]-sum2[y])*(i-x);//(x,i] (y,i] 1ll*(sum[i]-sum[x])/(i-x)<1ll*(sum[i]-sum[y])/(i-y)
});
}
dp[0][0]=1;
rep(i,1,n){
rep(j,1,n){//(i,j) 对于固定y i伸出去一段 用于固定左端点 j缩进来一段 dp值已知
int p1=0,p2=0,now=0;
while(p1<SZ(p[i]) && p2<SZ(q[j])){
int x=p[i][p1],y=q[j][p2];
if(1ll*(sum[x]-sum[i-1])*(j-y)<=1ll*(sum2[j]-sum2[y])*(x-i+1)){//[i,x] [y+1,j] 固定i和j
add(now,dp[i-1][y]);
p2++;
}
else{
add(dp[x][j],now);
p1++;
}
//printf("i:%d j:%d now:%d p1:%d p2:%d x:%d y:%d\n",i,j,now,p1,p2,x,y);
}
while(p1<SZ(p[i])){
int x=p[i][p1];
add(dp[x][j],now);
p1++;
}
//printf("i:%d j:%d dp:%d\n",i,j,dp[i][j]);
}
}
pte(dp[n][n]);
return 0;
}