BZOJ 1864 三色二叉树(树DP)

来源:互联网 发布:old456的新域名 编辑:程序博客网 时间:2024/04/28 04:58

Description

Input

仅有一行,不超过500000个字符,表示一个二叉树序列。

Output

输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。

Sample Input

1122002010

Sample Output

5 2

树DP问题:经典的去最大和最小=-=没啥说的,递归建树。

dp[i][0]: i节点不为绿色获得的最大收益
dp[i][1]:i节点为绿色获得的最大收益
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;const int maxn=1e5+100;int l[maxn],r[maxn],sz;LL dp[maxn][2];//三种颜色的最多的那个1:NOT 绿 2:绿char str[maxn];void dfs(int x){    if(str[x-1]=='0')        return ;    sz++;l[x]=sz;    dfs(sz);    if(str[x-1]=='2')    {        sz++;        r[x]=sz;        dfs(sz);    }}void hehe1(int u){    if(!u)        return ;    dp[u][1]=1;    dp[u][0]=0;    hehe1(l[u]);    hehe1(r[u]);    dp[u][1]+=dp[l[u]][0]+dp[r[u]][0];    dp[u][0]+=max(dp[l[u]][0]+dp[r[u]][1],dp[l[u]][1]+dp[r[u]][0]);//选其他颜色}void hehe2(int u){    if(!u)        return ;    dp[u][1]=1;    dp[u][0]=0;    hehe2(l[u]);    hehe2(r[u]);    dp[u][1]+=dp[l[u]][0]+dp[r[u]][0];    dp[u][0]+=min(dp[l[u]][0]+dp[r[u]][1],dp[l[u]][1]+dp[r[u]][0]);//选其他颜色}int main(){    int mi,mx;    while(~scanf("%s",str))    {        CLEAR(l,0);        CLEAR(r,0);        dfs(sz=1);        CLEAR(dp,0);        hehe1(1);        mx=max(dp[1][1],dp[1][0]);        hehe2(1);        mi=min(dp[1][1],dp[1][0]);        printf("%d %d\n",mx,mi);    }    return 0;}


0 0
原创粉丝点击