【UVA297】【洛谷】【树链剖分】

题目:我谷

代码:

#include <cstdio>
#include <cstring>
#define null NULL
char s1[100001],s2[100001];
struct node
{
    char c;
    node *ch[5];//孩子数组
    node()
    {
        c=0;
        ch[1]=ch[2]=ch[3]=ch[4]=null;//初始化为NULL
    }
    node(char _c)//字符构造函数
    {
        c=_c;
        ch[1]=ch[2]=ch[3]=ch[4]=null;
    }
};
char *cur;//make函数使用,表示当前处理的字符
node *make()
{
    if(*cur=='f')
    {
        node *tmp=new node('f');//返回黑节点
        return tmp;
    }
    if(*cur=='e')
    {
        node *tmp=new node('e');//返回白节点
        return tmp;
    }
    if(*cur=='p')
    {
        node *tmp=new node('p');//首先现将该节点的颜色设为灰
        for(int i=1;i<=4;++i)
        {
            ++cur;//指针后移
            tmp->ch[i]=make();//递归构建子树
        }
        return tmp;//返回节点
    }
    return null;//防CE
}
node *add(node *n1,node *n2)
{
    if(n1==null&&n2==null)//只是为了保险
    {
        return null;
    }
    if(n1==null||n2==null)
    {
        return n1==null?n2:n1;
    }
    if(n1->c=='f'||n2->c=='f')//有一个黑节点
    {
        node *tmp=new node('f');
        return tmp;
    }
    else if(n1->c=='e'&&n2->c=='e')//全是白节点
    {
        node *tmp=new node('e');
        return tmp;
    }
    else
    {
        node *tmp=new node('p');//新建灰节点
        bool full=true;//此变量是为了计算是否合并完之后变成黑节点,比如▚和▞
        for(int i=1;i<=4;++i)
        {
            tmp->ch[i]=add(n1->ch[i],n2->ch[i]);//递归合并子树
            if(tmp->ch[i]->c!='f')//如果有一个像素不为黑则不设置为黑
            {
                full=false;
            }
        }
        if(full)//如果是黑节点
        {
            tmp=new node('f');//更新
        }
        return tmp;
    }
    return null;
}
int count(node *n1,int dep)//n1为当前节点,dep为当前深度
{
    if(n1==null)
    {
        return 0;
    }
    if(n1->c=='f')//黑节点
    {
        return (1024>>(dep*2));//计算该节点的像素数
    }
    if(n1->c=='e')//空节点
    {
        return 0;//直接返回0
    }
    if(n1->c=='p')
    {
        int ans=0;
        for(int i=1;i<=4;++i)
        {
            ans+=count(n1->ch[i],dep+1);//递归数像素
        }
        return ans;//返回
    }
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",s1+1,s2+1);
        cur=s1+1;//处理指针置为第一个字符串开头
        node *r1,*r2;//根节点
        r1=make();
        cur=s2+1;//同上
        r2=make();
        node *root=add(r1,r2);
        printf("There are %d black pixels.\n",count(root,0));//输出个数
    }
    return 0;
}

1.建树
如果当前像素是f,那么直接设成黑像素即可
如果当前像素是e,同理
如果为p,则需要递归扩展子树
2.相加
首先如果当前像素中有黑色,那么结果一定为黑
如果全为白,那么结果为白
否则递归扩展4个子树
3.数像素
如果为黑,则返回2^{10-dep*2}2
10−dep∗2
如果为白,则返回00
否则还是递归扩展4个子树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值