• 线段树 POJ 3468


      这周学习了一下线段树,偶遇POJ 3468,这道题是线段树区间更新,题意大概是有一段的长为n的数组,经过若干次对其中某一段的数进行加减,询问某一段的和。这题还是比较明显的线段树,如果细分到对每一个节点进行操作的话,复杂度为O(m^logn),容易超时,所以采取延迟标记的做法,直接对某一段进行操作,而暂不对其子树进行操作,话不多说,直接上代码吧

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include <iostream>  
    #include<algorithm>
    #include<cmath>
    using  namespace  std; 
    
    struct node 
    {
        int x,y,sign;
        long long sum,ad; 
    } ;
    
    node tree[400010];
    long long v[100010];
    
    long long maketree(int x,int y,int z)
    {
        tree[z].x=x;
        tree[z].y=y;
        if(x>=y) return tree[z].sum=v[x];
        else return tree[z].sum=maketree(x,(x+y)/2,2*z)+maketree((x+y)/2+1,y,2*z+1);
    }
    
    void down(int q)
    {
        tree[q].sign=0;
        tree[2*q].sign=tree[2*q+1].sign=1;
        tree[2*q].ad+=tree[q].ad;
        tree[2*q+1].ad+=tree[q].ad;
        tree[2*q].sum+=tree[q].ad*(tree[2*q].y-tree[2*q].x+1);
        tree[2*q+1].sum+=tree[q].ad*(tree[2*q+1].y-tree[2*q+1].x+1);
        tree[q].ad=0;
    }
    
    void add(int x,int y,int z,int q)
    {
        if(x<=tree[q].x&&y>=tree[q].y) 
        {
            tree[q].sign=1;
            tree[q].sum+=z*(tree[q].y-tree[q].x+1);
            tree[q].ad+=z;
            return ;
        }
        if(tree[q].sign==1) down(q);
        if(x<=(tree[q].x+tree[q].y)/2) add(x,y,z,2*q);
        if(y>=(tree[q].x+tree[q].y)/2+1) add(x,y,z,2*q+1);
        tree[q].sum=tree[2*q].sum+tree[2*q+1].sum;
        return; 
    }
    
    long long find(int x,int y,int q)
    {
        if(x>tree[q].y||y<tree[q].x) return 0;
        if(x<=tree[q].x&&y>=tree[q].y) return tree[q].sum;
        if(tree[q].sign==1) down(q);
        return find(x,y,2*q)+find(x,y,2*q+1);
    }
    
    int main()
    {
        int n,q,x,y,z,i,k;
        long long sum;
        char ch;
        scanf("%d%d",&n,&q);
        memset(tree,0,sizeof(tree));
        for(k=1;k<=n;k++)
        {
            scanf("%lld",&v[k]);
        }
        maketree(1,n,1);
        for(i=1;i<=q;i++)
        {
            scanf("%*c%c",&ch);
            if(ch=='C')
            {
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z,1);
            }
            else if(ch=='Q')
            {
                scanf("%d%d",&x,&y);
                sum=find(x,y,1);
                printf("%lld
    ",sum);
            }
        }
        return 0;
    }
  • 相关阅读:
    可重入函数
    进程间通信的方法和实现
    Qt之Qprocess
    mysql学习(十二)内置函数
    mysql学习(十一)嵌套查询 排序 分组
    mysql学习(十)多表查询
    ubuntu 12.04 安装谷歌浏览器
    mysql学习(九)sql语句
    mysql学习(八)数据表类型-字符集
    mysql远程连接问题-http://www.cnblogs.com/jerome-rong/archive/2013/03/05/2944264.html
  • 原文地址:https://www.cnblogs.com/5299bbcl/p/4540886.html
Copyright © 2020-2023  润新知