CF848D Shake It!
可惜了,迟到了一个小时没时间做了。
首先我们发现,如果一条边上只能新建一个点是平凡的,因为这个类似三角剖分的过程帮我们划分了dp状态:设\(dp_{i,j}\)表示\(i\)个点,最小割为\(j\)的方案数。则可以从\(dp_{k,a}\times dp_{i-k,b}[\min(a,b)=j]\)转移。
但是现在一条边上还可以建很多点,并且注意,这里两个一样的点先后加入只算一种方案。因此需要特殊转移:对于每个\(w=dp_{k,a}\times dp_{i-k,b}[\min(a,b)=j]\),若其在最终状态中形成了\(k\)次,则方案数为\(C_{k}^{w+k-1}\),可以由其dp的组合意义证明。这样有\(O(n^4)\)个数需要转移,每个转移是\(O(n^2\ln n)\)的,因此总复杂度\(O(n^6\ln n)\)。但是能过
我们需要更优秀的复杂度,容易发现对于所有\(O(n^2)\)状态,能转移的\(O(n^4)\)个数只有\(O(n^2)\)种不同的取值,因此可以将所有取值相同的点合并成一次做背包,这样可以做到\(O(n^4\ln n)\)。
code:
#include<bits/stdc++.h>
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=400+5,M=1<<18|5,K=200+5,mod=1e9+7,Mod=mod-1;const db eps=1e-5;
int n,m,k,S[N],T[N],z,Ns[N],Nh,A[N][N],suf[N][N],pre[N][N],Ts,B[N][N];
int main(){
freopen("1.in","r",stdin);
int i,j,h,x,y;scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&S[i],&T[i]),T[i]+=S[i]-1,Ns[++Nh]=S[i],Ns[++Nh]=T[i];sort(Ns+1,Ns+Nh+1);Nh=unique(Ns+1,Ns+Nh+1)-Ns-1;
for(i=1;i<=n;i++) for(S[i]=LB(Ns+1,Ns+Nh+1,S[i])-Ns,T[i]=LB(Ns+1,Ns+Nh+1,T[i])-Ns,j=1;j<=S[i];j++) for(h=T[i];h<=Nh;h++) A[j][h]++;
Me(pre,-0x3f);Me(suf,-0x3f);pre[0][0]=0;suf[Nh+1][0]=0;for(i=1;i<=Nh;i++){
Mc(pre[i],pre[i-1]);for(j=0;j<i;j++) for(h=0;h<=j;h++) pre[j][h]>=0&&(pre[i][pre[j][h]+A[j+1][i]]=max(pre[i][pre[j][h]+A[j+1][i]],h),pre[i][h]=max(pre[i][h],pre[j][h]+A[j+1][i]));
}for(i=Nh;i;i--){
Mc(suf[i],suf[i+1]);for(j=i+1;j<=Nh+1;j++) for(h=0;h<=Nh-j+1;h++) suf[j][h]>=0&&(suf[i][suf[j][h]+A[i][j-1]]=max(suf[i][suf[j][h]+A[i][j-1]],h),suf[i][h]=max(suf[i][h],suf[j][h]+A[i][j-1]));
}for(i=0;i<=n;i++) Ts=max(Ts,min(i,pre[Nh][i]));printf("%d\n",Ts);
for(i=1;i<=Nh;i++){
for(j=i;j<=Nh;j++){
int R=Nh-j;for(x=0;x<i;x++){
while(R&&x+R+A[i][j]>pre[i-1][x]+suf[j+1][R]) R--,B[i][j]=max(B[i][j],min(x+R+A[i][j],pre[i-1][x]+suf[j+1][R]));
B[i][j]=max(B[i][j],min(x+R+A[i][j],pre[i-1][x]+suf[j+1][R]));
}//for(y=0;y<=Nh-j;y++) B[i][j]=max(B[i][j],min(x+y+A[i][j],pre[i-1][x]+suf[j+1][y]));
}
}
for(i=1;i<=n;printf("%d\n",Ts),i++) for(Ts=0,j=1;j<=S[i];j++) for(h=T[i];h<=Nh;h++) Ts=max(Ts,B[j][h]);
}