SPOJ 1557(线段树)

本文介绍了一个利用线段树解决区间最大连续和问题的方法,包括构造线段树、离线算法处理询问以及关键的pushdown函数实现。

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

题意大概是说给定一个区间,求最大连续和

完全不会,学习了半天

大概可以理解为一个线段树点更新,区间询问的题目,但是构造和理解起来相对难许多。

 

这里相同数的处理还是蛮有意思。用pre[i]记录i上一次出现的位置。所以update的时候跳过这个位置就好

用离线算法,将询问区间按r排序后,从第一个至最后一个数依次加入线段树,同时维护四个值:

1.sum 目前区间和

2.maxo 最大区间和

3.lazy 待下传的和

4.lazyo 待下传的最大可更新值

 

最关键的是pushdown函数

sum、lazy和普通的更新没什么区别,重点在于maxo和lazyo

可以注意到,当lazy<=0时,lazyo是一直为0的。因为如果加入的连续和<=0,maxo不可能被更新

lazy和lazyo不可分别写一个if,因为lazy将更新sum,而sum的更新可能会改变maxo

具体看代码

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"vector"
#define ll long long
#define mems(a,b) memset(a,b,sizeof(a))
#define ls pos<<1
#define rs pos<<1|1

using namespace std;
const int MAXN = 100500;
const int MAXE = 200500;
const int INF = 0x3f3f3f;

struct node{
    int l,r;
    ll sum,maxo,lazyo,lazy;
}node[MAXN<<2];

struct nod{
    int a,b,id;
}que[MAXN];

int pre[MAXN*2+10];
ll ans[MAXN],x[MAXN];

bool cmp(nod x,nod y){
    return x.b<y.b;
}

void build(int l,int r,int pos){
    node[pos].l=l;
    node[pos].r=r;
    node[pos].lazy=node[pos].lazyo=0;
    node[pos].sum=node[pos].maxo=0;
    if(l==r) return;
    int mid=(l+r)>>1;;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
}

void pushup(int pos){
    node[pos].sum=max(node[ls].sum,node[rs].sum);
    node[pos].maxo=max(node[ls].maxo,node[rs].maxo);
}

void pushdown(int pos){
    if(node[pos].lazy||node[pos].lazyo){
        node[ls].lazyo=max(node[ls].lazyo,node[ls].lazy+node[pos].lazyo);
        node[ls].maxo=max(node[ls].maxo,node[ls].sum+node[pos].lazyo);
        node[ls].lazy+=node[pos].lazy;
        node[ls].sum+=node[pos].lazy;

        node[rs].lazyo=max(node[rs].lazyo,node[rs].lazy+node[pos].lazyo);
        node[rs].maxo=max(node[rs].maxo,node[rs].sum+node[pos].lazyo);
        node[rs].lazy+=node[pos].lazy;
        node[rs].sum+=node[pos].lazy;

        node[pos].lazy=node[pos].lazyo=0;
    }
}

void update(int l,int r,int pos,int add){
    if(l<=node[pos].l&&node[pos].r<=r){
        node[pos].sum+=add;
        node[pos].lazy+=add;
        node[pos].lazyo=max(node[pos].lazyo,node[pos].lazy);
        node[pos].maxo=max(node[pos].sum,node[pos].maxo);
        return;
    }
    pushdown(pos);
    int mid=(node[pos].l+node[pos].r)>>1;
    if(l<=mid) update(l,r,ls,add);
    if(r>mid) update(l,r,rs,add);
    pushup(pos);
}

ll query(int l,int r,int pos){
    if(l<=node[pos].l&&node[pos].r<=r){
        return node[pos].maxo;
    }
    ll t=0;
    pushdown(pos);
    int mid=(node[pos].l+node[pos].r)>>1;
    if(l<=mid) t=max(t,query(l,r,ls));
    if(r>mid) t=max(t,query(l,r,rs));
    return t;
}

int main(){
    int n,q;
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++) scanf("%lld",&x[i]);
        build(1,n,1);
        scanf("%d",&q);
        for(int i=0;i<q;i++){
            scanf("%d%d",&que[i].a,&que[i].b);
            que[i].id=i;
        }
        sort(que,que+q,cmp);
        mems(pre,0);
        int j=0;
        for(int i=1;i<=n;i++){
            update(pre[MAXN+x[i]]+1,i,1,x[i]);
            pre[MAXN+x[i]]=i;
            while(j<q&&que[j].b==i){
                ans[que[j].id]=query(que[j].a,que[j].b,1);
                j++;
            }
        }
        for(int i=0;i<q;i++) printf("%lld\n",ans[i]);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/luxiaoming/p/5122303.html

内容概要:该研究通过在黑龙江省某示范村进行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、付费专栏及课程。

余额充值