[HDU-6854] Kcats (2020多校7 T11) (笛卡爾樹+區間dp)
阿新 • • 發佈:2020-08-11
[HDU-6854] Kcats (2020多校7 T11) (笛卡爾樹+區間dp)
字首\(p_1,p_2,\cdots,p_i\)的單調棧大小,即\(i\)號節點在全域性的笛卡爾樹上對應的位置的所有在左邊的祖先個數
因此,區間\(dp\)笛卡爾樹的樹形,合併時,為了滿足題目的限制,只需要記錄左邊的祖先個數\(d\)
即定義\(dp[l][r][d]\)為區間\(l,r\)對應笛卡爾樹子樹,且根節點左祖先個數為\(d\)的方案數
合併兩個子樹時注意補上組合數,且自己這個點對於左兒子深度沒有貢獻
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i) template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); } char IO; template <class T=int> T rd(){ T s=0; int f=0; while(!isdigit(IO=getchar())) if(IO=='-') f=1; do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return f?-s:s; } const int N=1e2+10,P=1e9+7; int n,a[N],C[N][N],dp[N][N][N]; int main(){ rep(i,0,N-1) rep(j,C[i][0]=1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P; rep(kase,1,rd()) { rep(i,1,n=rd()) a[i]=rd(); memset(dp,0,sizeof dp); drep(i,n,1) rep(j,i,n) rep(k,i,j) rep(d,~a[k]?a[k]:1,~a[k]?a[k]:n) dp[i][j][d]=(dp[i][j][d]+1ll*(i<k?dp[i][k-1][d]:1)*(k<j?dp[k+1][j][d+1]:1)%P*C[j-i][k-i])%P; printf("%d\n",dp[1][n][1]); } }