hdu-5861 线段树

来源:互联网 发布:简单数据库设计实例 编辑:程序博客网 时间:2024/06/07 20:49

http://acm.hdu.edu.cn/showproblem.php?pid=5861

题意是每段路有路灯,每个路灯只能开关一次,每个路灯开一天需要一定花费,给定每天需要用的路灯线段,求每一天的总的最小花费

因为只能开关一次,所以路灯的花费必定就是从第一次使用一直到最后一次使用,这样就是线段树裸的区间修改操作了

最后整体查询一遍,对每个路灯使用的日期,左端点加,右端点减,前缀和即花费

#include<bits/stdc++.h>using namespace std;const int maxn=2e5+10;int seg[4*maxn],be[4*maxn],lazy[4*maxn];int w[maxn],ans[maxn];void pushdown(int node){    if(lazy[node])    {        seg[node<<1]=lazy[node];        seg[node<<1|1]=lazy[node];        lazy[node<<1]=lazy[node];        lazy[node<<1|1]=lazy[node];        lazy[node]=0;    }    if(be[node])    {        if(!be[node<<1])            be[node<<1]=be[node];        if(!be[node<<1|1])            be[node<<1|1]=be[node];    }}void update(int L,int R,int k,int node,int l,int r){    if(l>=L&&r<=R)    {  //      cout<<l<<" "<<r<<" "<<k<<endl;        seg[node]=k;        lazy[node]=k;        if(be[node]==0)            be[node]=k;        return ;    }    pushdown(node);    int m=(l+r)>>1;    if(m>=L)    {        update(L,R,k,node<<1,l,m);    }    if(m<R)    {        update(L,R,k,node<<1|1,m+1,r);    }}int query(int l,int r,int node){    if(l==r)    {   //     cout<<l<<" "<<seg[node]<<" "<<be[node]<<endl;        if(seg[node])        {            ans[be[node]]+=w[l];            ans[seg[node]+1]-=w[l];        }        return 0;    }    pushdown(node);    int m=(l+r)>>1;    query(l,m,node<<1);    query(m+1,r,node<<1|1);}int main(){    int n,m,i,a,b;    while(cin>>n>>m)    {        memset(seg,0,sizeof(seg));        memset(be,0,sizeof(be));        memset(ans,0,sizeof(ans));        memset(lazy,0,sizeof(lazy));        for(i=1;i<n;i++)            scanf("%d",&w[i]);        for(i=1;i<=m;i++)        {            scanf("%d %d",&a,&b);            if(a>b)                swap(a,b);            b--;            update(a,b,i,1,1,n-1);        }        query(1,n-1,1);        int now=0;        for(i=1;i<=m;i++)        {            now+=ans[i];;            printf("%d\n",now);        }    }    return 0;}