poj 2777 Count Color

本文深入探讨了一道关于线段树的数据结构题目,通过实例详细解释了如何利用线段树来统计一块木板上出现的颜色种类,介绍了核心概念如懒标记、颜色编码,并提供了完整的实现代码。

问题描述:http://poj.org/problem?id=2777

理解:

一道线段树的题。

统计一块木板上出现颜色的种类。相对纯粹和的累加还是不一样。涂上新的颜色会被覆盖掉,找不到合适的容器。

还有lazy算法,避免每一次搜索得把所有叶子节点遍历一遍

细节:

1."P A B" (here A, B, C are integers, and A may be larger than B) 意味着出现此种情况要交换

2.节点里还是不要Mid(),占空间。

解决办法:

1.用一个32位的整数,记录每一种颜色出现。解决覆盖可以用左右叶子节点  |  。计算颜色种数用移位>>。

2.两个操作

Color()这个函数的递归让我挺晕的。据我目前看来的递归函数,在调用自身之前常往下一步走,也就是“push up”, 调用自身之后,会反馈回来,

也就是“push down”。查询这个操作里,因为要用lazy算法,终止条件几乎都是,当前节点范围被s、e覆盖。

Output()这个函数里要返回颜色这个32位整数。在最后一个判断条件里是用符号 | 进行种数的累加,而不是单纯的加和,我就wa在这里了。

3.标记flag为1的时候表示只有当前区间只有一种颜色(可以选择push down);为0的时候就已经有多种颜色了。


代码:

#include <iostream>
#include <cstdio>

#define N 100050

using namespace std;

struct Node
{
    int L, R, flag;
    int C;    //32位整数
    int Mid()
    {
        return (L + R)/2;
    }
} tree[N * 4];

int amount(int c)
{
    int a = 0;
    while(c != 0)
    {
        if((c & 1) == 1)
        {
            a++;
        }
        c >>= 1;
    }
    return a;
}
/*
void print(int root)
{
    cout << tree[root].L << " " << tree[root].R << endl;
    cout << tree[root].flag << endl;
    cout << amount(tree[root].C) << endl << endl;
}
*/

void BuildTree(int root, int L, int R)
{
    tree[root].L = L;
    tree[root].R = R;
    tree[root].C = 1;
    tree[root].flag = 1;//

    if(L != R)
    {
        BuildTree(root * 2 + 1, L, (L + R)/2);
        BuildTree(root * 2 + 2, (L + R)/2 + 1, R);
    }
}

void color(int root, int s, int e, int t)
{
    if(s <= tree[root].L && tree[root].R <= e)
    {
        tree[root].C = (1 << (t - 1));
        tree[root].flag = 1;
        //print(root);
        return;
    }
    if(tree[root].flag)
    {
        tree[root * 2 + 1].C = tree[root * 2 + 2].C = tree[root].C;
        tree[root * 2 + 1].flag = tree[root * 2 + 2].flag = 1;
        tree[root].flag = 0;
    }

    if(e <= tree[root].Mid())
    {
        color(root * 2 + 1, s, e, t);
    }
    else if(s > tree[root].Mid())
    {
        color(root * 2 + 2, s, e, t);
    }
    else
    {
        color(root * 2 + 1, s, tree[root].Mid(), t);
        color(root * 2 + 2, tree[root].Mid() + 1, e, t);
    }
    tree[root].C = tree[root * 2 + 1].C | tree[root * 2 + 2].C;
    tree[root].flag = 0;
}

int output(int root, int s, int e)
{
    if((s <= tree[root].L && tree[root].R <= e) || tree[root].flag)
    {
        return tree[root].C;
    }

    if(e <= tree[root].Mid())
    {
        return output(root * 2 + 1, s, e);
    }
    else if(s > tree[root].Mid())
    {
        return output(root * 2 + 2, s, e);
    }
    else
    {
        return output(root * 2 + 1, s, tree[root].Mid()) | output(root * 2 + 2, tree[root].Mid() + 1, e);
    }

}

int main()
{
    int L, T, O;
    scanf("%d%d%d", &L, &T, &O);
    //cin >> L >> T >> O;

    BuildTree(0, 1, L);

    for(int i = 0; i < O; i++)
    {
        char c;
        int s, e, t;

        getchar();
        scanf("%c", &c);
        //cin >> c;
        if(c == 'C')
        {
            scanf("%d%d%d", &s, &e, &t);
            //cin >> s >> e >> t;
            color(0, s, e, t);
            /*
            for(int i = 0; i <  L + 1; i++)
            {
                print(i);
            }
            */

        }
        else if(c == 'P')
        {
            scanf("%d%d", &s, &e);
            //cin >> s >> e;
            if(s > e)
                swap(s, e);

            printf("%d\n", amount(output(0, s, e)));
            //cout << A << endl;
        }
    }

    return 0;
}


【顶级EI完美复现】电力系统碳排放流的计算方法【IEEE 14节点】(Matlab代码实现)内容概要:本文介绍了名为《【顶级EI完美复现】电力系统碳排放流的计算方法【IEEE 14节点】(Matlab代码实现)》的技术文档,核心内容是基于IEEE 14节点电力系统模型,利用Matlab实现碳排放流的精确计算方法。该方法通过建立电力系统中各节点的功率流动与碳排放之间的映射关系,实现对电能传输过程中碳足迹的追踪与量化分析,属于电力系统低碳调度与碳流管理领域的关键技术。文中强调“顶级EI完美复现”,表明其算法和仿真结果具有较高的学术严谨性和可重复性,适用于科研验证与教学演示。; 适合人群:电力系统、能源与动力工程、电气工程及其自动化等相关专业的研究生、科研人员以及从事电力系统低碳化、碳排放核算工作的技术人员。; 使用场景及目标:①用于电力系统碳排放流理论的学习与仿真验证;②支撑含新能源接入的电力系统低碳调度、碳交易、绿色电力溯源等课题的研究;③为撰写高水平学术论文(如EI/SCI期刊)提供可靠的代码基础和技术参考。; 阅读建议:读者应具备电力系统分析、Matlab编程的基础知识,建议结合电力系统潮流计算、节点导纳矩阵等前置知识进行学习,并通过调整系统参数和运行方式,深入理解碳排放流的分布规律与影响因素。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值