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;
}
View Code

 

posted @ 2019-03-13 19:45  寒雨微凝  阅读(127)  评论(0编辑  收藏  举报