BZOJ3227 [sdoi2008]红黑树
贪心什么的太神仙了(
老老实实dp于是就是沙茶题了
f[i][d][0/1]表示i个节点bh为d当前节点颜色白/黑【好好读题是真。。
转移一下然后就可以打表了(
由于我们发现这玩意很好卡有很好的性质(平衡树嘛)于是就优化一下转移啥的就能啊次了
memset真的是个很迷的东西。5000*5000的数组就过不了了233
读不对题郁闷死了(课内也读不对咋整啊。
//Love and Freedom. #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define ll long long #define inf 20021225 #define N 5100 using namespace std; int f[N][21][2],g[N][21][2],lg[21]; int main() { int n;//freopen("qwq.out","w",stdout); scanf("%d",&n); lg[0]=1; for(int i=1;i<20;i++) lg[i]=lg[i-1]<<1; memset(f,48,sizeof(f)); f[0][1][1]=0;//f[1][1][1]=0;f[2][1][0]=1; memset(g,-48,sizeof(g)); g[0][1][1]=0;//g[1][1][1]=0;g[2][1][0]=1; for(int i=1;i<=n;i++) for(int d=1;lg[d-1]<=n+1&&d<=i+1;d++) { for(int k=(d>1?(1<<d-2)-1:0);k<=i-k-1;k++) { f[i][d][0]=min(f[i][d][0],f[i-k-1][d][1]+f[k][d][1]+1); g[i][d][0]=max(g[i][d][0],g[i-k-1][d][1]+g[k][d][1]+1); if(d) f[i][d][1]=min(f[i][d][1],min(f[i-k-1][d-1][0],f[i-k-1][d-1][1])+min(f[k][d-1][0],f[k][d-1][1])), g[i][d][1]=max(g[i][d][1],max(g[i-k-1][d-1][0],g[i-k-1][d-1][1])+max(g[k][d-1][0],g[k][d-1][1])); } } int ans1=inf,ans2=0; for(int i=1;lg[i-1]<=n+1;i++) { ans1=min(ans1,min(f[n][i][0],f[n][i][1])), ans2=max(ans2,max(g[n][i][0],g[n][i][1])); } printf("%d\n%d\n",ans1,ans2); return 0; }