美文网首页数据结构
线段树的训练

线段树的训练

作者: 碧影江白 | 来源:发表于2016-08-29 18:34 被阅读23次

    HDU 1754 I Hate It
    求某个范围内数据的最值,为线段树的基本功能。
    在数据更新时使用不太熟练,另外由于没有注意到<<和+的优先值,使程序出错。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    using namespace std;
    
    int Max_num=-99999;
    struct 
    {
        int left;
        int right;
        int value;
    }node[800010];
    
    
    
    void build (int i,int ll,int rr)
    {
        node[i].left=ll;
        node[i].right=rr;
        node[i].value=0;
        if (ll==rr)
        {
            return;
        }
        build(i<<1,ll,(ll+rr)/2);
        build((i<<1)+1,(ll+rr)/2+1,rr);
    }
    
    void max(int i,int ll,int rr)
    {
        if (node[i].left==ll&&node[i].right==rr)
        {
            Max_num=(Max_num>node[i].value)?Max_num:node[i].value;
            return;
        }
        i=i<<1;
        if (node[i].right>=ll)
        {
            if(node[i].right>=rr)
                max(i,ll,rr);
            else
                max(i,ll,node[i].right);
        }
        i++;
        if (node[i].left<=rr)
        {
            if (node[i].left<=ll)
                max(i,ll,rr);
            else
                max(i,node[i].left,rr);
        }
    }
    
    
    void update(int i,int nu,int k)
    {
        if (node[k].left==node[k].right)
        {
            node[k].value=nu;
            return;
        }
        int mid=(node[k].left+node[k].right)/2;
        if (i<=mid)
        {
            update(i,nu,2*k);
        }
        else if (i>mid)
        {
            update(i,nu,2*k+1);
        }
        node[k].value=(node[2*k].value>node[2*k+1].value)?node[2*k].value:node[2*k+1].value;
    }
    
    
    void main()
    {
        int i,j,k,n,m,a,b,K;
        char ch;
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            build(1,1,n);
            for (i=1;i<=n;i++)
            {
                scanf("%d",&K);
                update(i,K,1);
            }
            for(j=1;j<=m;j++)
            {
                getchar();
                scanf("%c%d%d",&ch,&a,&b);
                if (ch=='Q')
                {
                    max(1,a,b);
                    printf("%d\n",Max_num);
                    Max_num=-99999;
                }
                else if (ch=='U')
                {
                    update(a,b,1);
                }
            }
        }
    }
    

    hdu1698 Just a Hook
    改变某一范围内的数的值,求总的和,这道题是一片你过的方法为成段更新:即只对父节点更新,而子节点不更新,由于最终求和的对象是总的和,故不会影响。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int MAXN=100010;
    struct Node
    {
        int l,r;
        int lazy,tag;
        int sum;
    }segTree[MAXN*3];
    void Build(int i,int l,int r)
    {
        segTree[i].l=l;
        segTree[i].r=r;
        segTree[i].lazy=0;
        segTree[i].tag=0;
        if(l==r)
        {
            segTree[i].sum=1;
            return;
        }
        int mid=(l+r)>>1;
        Build(i<<1,l,mid);
        Build((i<<1)|1,mid+1,r);
        segTree[i].sum=segTree[i<<1].sum+segTree[(i<<1)|1].sum;
    }
    void update(int i,int l,int r,int v)
    {
        if(segTree[i].l==l&&segTree[i].r==r)//成段更新
        {
            segTree[i].lazy=1;
            segTree[i].tag=v;
            segTree[i].sum=(r-l+1)*v;
            return;
        }
        int mid=(segTree[i].l+segTree[i].r)>>1;
        if(segTree[i].lazy==1)
        {
            segTree[i].lazy=0;
            update(i<<1,segTree[i].l,mid,segTree[i].tag);
            update((i<<1)|1,mid+1,segTree[i].r,segTree[i].tag);
            segTree[i].tag=0;
        }
        if(r<=mid) update(i<<1,l,r,v);
        else if(l>mid)update((i<<1)|1,l,r,v);
        else
        {
            update(i<<1,l,mid,v);
            update((i<<1)|1,mid+1,r,v);
        }
        segTree[i].sum=segTree[i<<1].sum+segTree[(i<<1)|1].sum;
    }
    int main()
    {
          //  freopen("in.txt","r",stdin);
     //  freopen("out.txt","w",stdout);
        int x,y,z;
        int n;
        int m;
        int T;
        scanf("%d",&T);
        int iCase=0;
        while(T--)
        {
            iCase++;
            scanf("%d%d",&n,&m);
            Build(1,1,n);
            while(m--)
            {
                scanf("%d%d%d",&x,&y,&z);
                update(1,x,y,z);
            }
            printf("Case %d: The total value of the hook is %d.\n",iCase,segTree[1].sum);
        }
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:线段树的训练

        本文链接:https://www.haomeiwen.com/subject/vgaxettx.html