HDU 4107 Gangster (线段树)

来源:互联网 发布:手机号码归属地数据库 编辑:程序博客网 时间:2024/05/02 02:43

       这道题,一看题大概就知道是线段树。

       对于这种题通常来说就是看节点中如何记录信息了……

       这道题我们使用:

v记录区间的改变值,也就是在update过程中累加的改变值

Max表示整个区间的最大值

Min表示整个区间的最小值

当然还有l和r不用说了。

        当一个区间的Max<p的时候我们就对这个区间的v值加上c,当一个区间的的Min>=p的时候,我们就将这个区间的v值加上2*c;等到所有的update完成之后,直接查询每个点的v值就是最终输出的答案了……

         如果不会写可以看下代码:

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;const int Max= 200010;typedef struct SEGMENT{    int l,r;    int v,Max,Min;}Segment;Segment seg[Max*4];int n,m,p;int inline max(int a,int b){    if(a<b) return b;    else    return a;}int inline min(int a,int b){    if(a<b) return a;    else    return b;}void init(int l,int r,int k){    seg[k].l=l,seg[k].r=r;    seg[k].v=seg[k].Max=seg[k].Min=0;    if(l==r)        return ;    init(l,(l+r)>>1,k<<1);    init(((l+r)>>1)+1,r,(k<<1)+1);}void inline pushDown(int k){    int v=seg[k].v;    if(seg[k].v>0)    {        seg[k<<1].v+=seg[k].v,seg[k<<1].Min+=v,seg[k<<1].Max+=v;        seg[(k<<1)+1].v+=seg[k].v,seg[(k<<1)+1].Min+=v,seg[(k<<1)+1].Max+=v;        seg[k].v=0;    }}void inline pushUp(int k){    seg[k].Max=max(seg[k<<1].Max,seg[(k<<1)+1].Max);    seg[k].Min=min(seg[k<<1].Min,seg[(k<<1)+1].Min);}void update(int l,int r,int c,int k){    if(seg[k].l==l&&seg[k].r==r&&(seg[k].Max<p||seg[k].Min>=p))    {        if(seg[k].Max<p)        {            seg[k].v+=c;            seg[k].Max+=c;            seg[k].Min+=c;        }        else if(seg[k].Min>=p)        {            seg[k].v+=(c<<1);            seg[k].Max+=(c<<1);            seg[k].Min+=(c<<1);        }        return ;    }    if(seg[k].v)        pushDown(k);    int mid=(seg[k].l+seg[k].r)>>1;    if(r<=mid)        update(l,r,c,k<<1);    else if(l>mid)        update(l,r,c,(k<<1)+1);    else    {        update(l,mid,c,2*k);        update(mid+1,r,c,2*k+1);    }    pushUp(k);}int read(int id,int k){    if(seg[k].l==id&&seg[k].r==id)    {        return seg[k].v;    }    if(seg[k].v>0)        pushDown(k);    int mid=(seg[k].l+seg[k].r)>>1;    if(id<=mid)        return read(id,k<<1);    else if(id>mid)        return read(id,(k<<1)+1);}int main(){    int a,b,c;    while(scanf("%d%d%d",&n,&m,&p)!=EOF)    {        init(1,n,1);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&a,&b,&c);            update(a,b,c,1);        }        for(int i=1;i<=n;i++)        {            printf("%d%c",read(i,1),i==n?'\n':' ');        }    }    return 0;}