hdu 1556(线段树)

这个是基础的线段树的区间修改和单点查询的题,线段树的区间问题写法很套路,然而,区间修改问题有一个是我们需要注意的地方,那就是添加lazy标记,什么时候添加lazy标记和lazy标记
表示的是什么,这个需要明白,lazy标记表示的是整个区间的偏移量,当我们需要向下查找的时候,这个时候我们就需要下放lazy标记。另一个需要注意的地方是区间修改问题,一定要记得
pushup,这个很重要,还有递归返回值的问题,学的还是不扎实啊
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define maxn 110000 using namespace std; int n; //区间修改,单点查询 struct node{ int l,r,sum,lazy; //lazy就是加上懒标记 }x[4*maxn+5]; void build(int l,int r,int p) { x[p].l=l; x[p].r=r; if(l==r) return; build(l,(l+r)/2,p<<1); build((l+r)/2+1,r,(p<<1)+1); } //延迟标记向下传 ,在哪个位置下传,这个很重要 void pushdown(int p) { if(x[p].lazy) { int a=(p<<1); x[a].lazy+=x[p].lazy; x[a+1].lazy+=x[p].lazy; x[a].sum=x[a].sum+x[p].lazy*(x[a].r-x[a].l+1); x[a+1].sum=x[a+1].sum+x[p].lazy*(x[a+1].r-x[a+1].l+1); x[p].lazy=0; } } //区间修改 void modi(int l,int r,int d,int p) { if(l>x[p].r||r<x[p].l) return; if(l<=x[p].l&&r>=x[p].r) {x[p].sum=x[p].sum+d*(x[p].r-x[p].l+1);x[p].lazy+=d;return;} else { int a=(p<<1); pushdown(p);//需要下传的时候才下传,因为这个时候才是真正往下走的时候 if(r<=x[a].r) modi(l,r,d,a); else if(l>=x[a+1].l) modi(l,r,d,a+1); else { modi(l,x[a].r,d,a); modi(x[a+1].l,r,d,a+1); } x[p].sum=x[p<<1].sum+x[p<<1|1].sum; } } //单点查询 int query(int q,int p,int d) { //if(l>x[p].r||r<x[p].l) return 0;这句话写上就错了 int ans=0; if(x[p].l==q&&x[p].r==q) return x[p].sum; pushdown(p); if(q>=x[p].l&&q<=x[p].r) { if(q<=x[p<<1].r) ans=query(q,p<<1,d); else ans=query(q,(p<<1)+1,d); } return ans; } int main() { int a,b; while(scanf("%d",&n)==1&&n!=0) { memset(x,0,sizeof(x)); build(1,n,1); for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); modi(a,b,1,1); } // for(int i=1;i<=n;i++) query(i,1,1); for(int i=1;i<=n-1;i++) printf("%d ",query(i,1,1)); printf("%d\n",query(n,1,1)); } return 0; }

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 110000
using namespace std;
int n;
//区间修改,单点查询 
struct node{
    int l,r,sum,lazy;
    //lazy就是加上懒标记 
}x[4*maxn+5];

void build(int l,int r,int p)
{
    x[p].l=l;
    x[p].r=r;
    if(l==r) return;
    build(l,(l+r)/2,p<<1);
    build((l+r)/2+1,r,(p<<1)+1);
}

//延迟标记向下传 ,在哪个位置下传,这个很重要 
void pushdown(int p)
{
    if(x[p].lazy)
    {
        int a=(p<<1);
        x[a].lazy+=x[p].lazy;
        x[a+1].lazy+=x[p].lazy;
        x[a].sum=x[a].sum+x[p].lazy*(x[a].r-x[a].l+1);
        x[a+1].sum=x[a+1].sum+x[p].lazy*(x[a+1].r-x[a+1].l+1);
        x[p].lazy=0;
    }
    
}

//区间修改 
void modi(int l,int r,int d,int p)
{
    if(l>x[p].r||r<x[p].l) return;
    if(l<=x[p].l&&r>=x[p].r) {x[p].sum=x[p].sum+d*(x[p].r-x[p].l+1);x[p].lazy+=d;return;}
    else
    {    
        int a=(p<<1);
        pushdown(p);//需要下传的时候才下传,因为这个时候才是真正往下走的时候 
        if(r<=x[a].r) modi(l,r,d,a);
        else if(l>=x[a+1].l) modi(l,r,d,a+1);
            else 
            {
                modi(l,x[a].r,d,a); 
                modi(x[a+1].l,r,d,a+1);
            }
        x[p].sum=x[p<<1].sum+x[p<<1|1].sum;
    }
}

//单点查询 
int query(int q,int p,int d)
{
    //if(l>x[p].r||r<x[p].l) return 0;这句话写上就错了
    int ans=0;
    if(x[p].l==q&&x[p].r==q) return x[p].sum;
    pushdown(p);
    if(q>=x[p].l&&q<=x[p].r)
    {
        if(q<=x[p<<1].r) ans=query(q,p<<1,d);
        else ans=query(q,(p<<1)+1,d);
    }
    return ans;    
}

int main()
{
    int a,b;
    while(scanf("%d",&n)==1&&n!=0)
    {
        memset(x,0,sizeof(x));
        build(1,n,1);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            modi(a,b,1,1);
        }
//        for(int i=1;i<=n;i++)  query(i,1,1);    
        for(int i=1;i<=n-1;i++) printf("%d ",query(i,1,1));    
        printf("%d\n",query(n,1,1));
    }
    return 0;
}
posted @ 2017-06-27 23:01  xinyimama  阅读(77)  评论(0)    收藏  举报