hdu 2871 Memory Control

本文介绍了一种利用线段树进行区间管理的方法,通过具体的实现案例,详细讲解了线段树的基本操作如查询、更新等,并展示了如何结合vector进行高效区间搜索与维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线段树

题意:1到n的线段,m个操作

Reset 将所有内存清空

New x 申请一段长度为x的最左的未被占用的区间,返回它的位置,并占用它。找不到输出Reject New

Free x 找到x单元内存所在的连续的单元块,返回这个单元块的左右端点,并且清空这个单元块,如果这个单元x根本没被占用,则输出Reject Free

Get x 找到第x个单元块(而不是第x单元),返回这个单元块的起始位置即左端点

 

这题还是和 poj 3667 Hotel 是一样的,查询一个最左的合法区间,修改一段区间

这题使用vector按顺序来保存单元块,方便查找(可以使用二分)

而线段树主要的query和updata函数是一样的

 

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define N 50010

struct block{
    int l,r;
};
struct node{
    int l,r;
    int mark;
    int tlen,llen,rlen;
    int mid(){
        return (l+r)>>1;
    }
    int cal_len(){
        return r-l+1;
    }
    void updata_len(){
        tlen=llen=rlen= (mark ? 0 : cal_len());
    }
};
typedef struct block Block;
typedef struct node node;
vector <Block> B;
node t[4*N];

void build(int l ,int r ,int rt)
{
    t[rt].l = l; t[rt].r = r; 
    t[rt].mark = 0;
    t[rt].updata_len();
    if(l == r) return ;
    int mid = t[rt].mid();
    int ll = lch(rt);
    int rr = rch(rt);
    build(l , mid , ll);
    build(mid+1 , r , rr);
    return ;
}

void updata(int l , int r , int val , int rt)
{
    if(t[rt].l == l && t[rt].r == r) 
    {
        t[rt].mark = val;
        t[rt].updata_len();
        return ;
    }
    int mid = t[rt].mid();
    int ll = lch(rt);
    int rr = rch(rt);
    
    if(t[rt].mark != -1)
    {
        t[ll].mark = t[rr].mark = t[rt].mark;
        t[rt].mark = -1;
        t[ll].updata_len();
        t[rr].updata_len();
    }

    if(l > mid)        updata(l , r , val , rr);
    else if(r <= mid)  updata(l , r , val , ll);
    else
    {
        updata(l , mid , val , ll);
        updata(mid+1 , r , val , rr);
    }

    t[rt].tlen = max( max(t[ll].tlen , t[rr].tlen)  ,  t[ll].rlen+t[rr].llen);
    t[rt].llen = t[ll].llen;  t[rt].rlen = t[rr].rlen;
    if(t[ll].tlen == t[ll].cal_len()) t[rt].llen += t[rr].llen;
    if(t[rr].tlen == t[rr].cal_len()) t[rt].rlen += t[ll].rlen;
    return ;
}

int query(int w , int rt)
{
    if(t[rt].l == t[rt].r)
    {
        if(w == 1) return t[rt].l;
        else       return 0;
    }

    int mid = t[rt].mid();
    int ll = lch(rt);
    int rr = rch(rt);
    
    if(t[rt].mark != -1)
    {
        t[ll].mark = t[rr].mark = t[rt].mark;
        t[rt].mark = -1;
        t[ll].updata_len();
        t[rr].updata_len();
    }

    if(t[ll].tlen >= w) 
        return query(w , ll);
    else if(t[ll].rlen + t[rr].llen >= w)
        return t[ll].r - t[ll].rlen + 1;
    else if(t[rr].tlen >= w)
        return query(w , rr);
    else
        return 0;
}

int binarysearch(int key)
{
    int low = 0;
    int high = B.size() - 1;
    while(low <= high)
    {
        int mid = (low + high) >> 1;
        if(B[mid].l <= key)
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low;
    //此二分查找最终返回low,二分查找要写好,否则很难查错
    //B[low]代表的块是大于pos的,B[low-1]小于pos
    //对于添加一个新的区间,是在low这里添加,原来的low以及后面的区间往后移动
    //对于删除一个区间,是low-1,low以及后面的区间往前移动
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        B.clear();
        build(1,n,1);
        while(m--)
        {
            char op[10];
            int x,pos,index;
            Block tmp;
            scanf("%s",op);
            if(!strcmp(op,"Reset"))
            {
                updata(1,n,0,1);
                B.clear();
                puts("Reset Now");
                continue;
            }

            scanf("%d",&x);
            if(!strcmp(op,"New"))
            {
                pos = query(x,1);
                if(!pos) 
                {
                    puts("Reject New");
                    continue;
                }
                printf("New at %d\n",pos);
                tmp.l = pos;  tmp.r = pos + x -1;
                index = binarysearch(pos);
                B.insert(B.begin()+index , tmp);
                updata(tmp.l , tmp.r , 1 , 1);
            }
            else if(!strcmp(op,"Free"))
            {
                index = binarysearch(x) - 1;
                if(index == -1 || B[index].r < x)
                {
                    puts("Reject Free");
                    continue;
                }
                printf("Free from %d to %d\n",B[index].l , B[index].r);
                updata(B[index].l , B[index].r , 0 , 1);
                B.erase(B.begin()+index , B.begin()+index+1);
            }
            else  //Get
            {
                if(--x >= B.size()) 
                {
                    puts("Reject Get");
                    continue;
                }
                printf("Get at %d\n",B[x].l);
            }
        }
        printf("\n");
    }
    return 0;
}

 

内容概要:该研究通过在黑龙江省某示范村进行24小时实地测试,比较了燃煤炉具与自动/手动进料生物质炉具的污染物排放特征。结果显示,生物质炉具相比燃煤炉具显著降低了PM2.5、CO和SO2的排放(自动进料分别降低41.2%、54.3%、40.0%;手动进料降低35.3%、22.1%、20.0%),但NOx排放未降低甚至有所增加。研究还发现,经济性和便利性是影响生物质炉具推广的重要因素。该研究不仅提供了实际排放数据支持,还通过Python代码详细复现了排放特征比较、减排效果计算和结果可视化,进一步探讨了燃料性质、动态排放特征、碳平衡计算以及政策建议。 适合人群:从事环境科学研究的学者、政府环保部门工作人员、能源政策制定者、关注农村能源转型的社会人士。 使用场景及目标:①评估生物质炉具在农村地区的推广潜力;②为政策制定者提供科学依据,优化补贴政策;③帮助研究人员深入了解生物质炉具的排放特征和技术改进方向;④为企业研发更高效的生物质炉具提供参考。 其他说明:该研究通过大量数据分析和模拟,揭示了生物质炉具在实际应用中的优点和挑战,特别是NOx排放增加的问题。研究还提出了多项具体的技术改进方向和政策建议,如优化进料方式、提高热效率、建设本地颗粒厂等,为生物质炉具的广泛推广提供了可行路径。此外,研究还开发了一个智能政策建议生成系统,可以根据不同地区的特征定制化生成政策建议,为农村能源转型提供了有力支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值