• 线段树区间更新&&求和poj3486


    给出了一个序列,你需要处理如下两种询问。
    "C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
    "Q a b" 询问[a, b]区间中所有值的和。
    Input
    第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.
    第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。
    接下来Q行询问,
    Sample Input
    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    Sample Output
    4
    55
    9
    15
    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    using namespace std;
    
    #define MAXSIZE 100005
    
    long long   val[MAXSIZE];
    long long  add[100010<<2];
    long long  sum[100010<<2];
    long long sum1;
    
    struct node
    {
       long long  total;
        int left;
        int right;
        int mark; //延时标记
    } tree[MAXSIZE*3];
    //下面两种create都可以,选择一种就可
    long long  create(int root,int left,int right)
    {
        add[root]=0;
        sum[root]=1;
        tree[root].left=left;
        tree[root].right=right;
        if(left==right)
            return tree[root].total=val[left];
        int middle=(left+right)>>1;
        return tree[root].total=create(root<<1,left,middle)+create(root<<1|1,middle+1,right);
    }
    // 参数:询问区间左端点,询问区间右端点,每个位置需要增加的值,当前节点序号
    void update(int L, int R, int x, int root)
    {
        if (L<=tree[root].left && tree[root].right<= R)
        {
            // 当前区间被包含,处理相应附加信息
            add[root] += x;    // 更新延迟标记
            tree[root].total+= x * (tree[root].right-tree[root].left+1);
            return;          // 暂时不用再向下递归
        }
        int mid = (tree[root].left+tree[root].right)>>1;
        if (add[root])   // 延迟标记不为0,说明有未完成的更新,更新之
        {
            add[root<<1] += add[root];
            add[root<<1|1] += add[root];
            tree[root<<1].total += add[root] * (mid-tree[root].left+1);
            tree[root<<1|1].total += add[root] * (tree[root].right-mid);
            add[root] = 0; // 不要忘了去除延迟标记
        }
        if (L <= mid)   // 左子区间中包含有更新区间的部分,需要更新
            update(L, R, x, root<<1);
        if (R > mid)     // 右子区间中包含有更新区间的部分,需要更新
            update(L, R, x, root<<1|1);
        tree[root].total = tree[root<<1].total + tree[root<<1|1].total;//从叶子节点向上更新
    }
    /*
    void find(tree *r,int a,int b){
       if(r->left==a&&r->right==b){
           sum+=r->data;
           return;
       }
       int mid=(r->left+r->right)>>1;
       if(b<=mid)
        find(r->lchild,a,b);
       else if(a>mid)
        find(r->rchild,a,b);
       else{
           find(r->lchild,a,mid);
        find(r->rchild,mid+1,b);
       }
    }*/
    //long long sum1;
    long long  cal(int root,int a,int b){
        if(a<=tree[root].left&&b>=tree[root].right){
           return tree[root].total;
        }
         int mid=(tree[root].left+tree[root].right)>>1;
        if(add[root]){
                add[root<<1] += add[root];
            add[root<<1|1] += add[root];
            tree[root<<1].total += add[root] * (mid-tree[root].left+1);
            tree[root<<1|1].total += add[root] * (tree[root].right-mid);
            add[root] = 0; // 不要忘了去除延迟标记
        
        }
    
       
        if(b<=mid)
         return  cal(root<<1,a,b);
        else if(a>mid)
            return cal(root<<1|1,a,b);
        else{
              return cal(root<<1,a,mid)+cal(root<<1|1,mid+1,b);
        }
    }
    
    int main(){
        int n,q;
        while(scanf("%d%d",&n,&q)!=EOF){
            for(int i=1;i<=n;i++){
                scanf("%lld",&val[i]);
            }
            memset(sum,0,sizeof(sum));
            memset(add,0,sizeof(add));
            long long tmp=create(1,1,n);
            char c;
            getchar();
            int a,b,d;
            for(int i=1;i<=q;i++){
                scanf("%c",&c);
                if(c=='C'){
                  scanf("%d %d %d",&a,&b,&d);
                    update(a,b,d,1);
                }
                else{
                    scanf("%d%d",&a,&b);
                   sum1=cal(1,a,b);
                  printf("%lld
    ",sum1);
    
                }
                getchar();
            }
        }
        return 0;
    }
    /*
    POJ 3468 A Simple Problem with Integers
    题目意思:
    给定Q个数:A1,A2,```,AQ,以及可能多次进行下列两个操作:
    1)对某个区间Ai```Aj的数都加n(n可变)
    2)对某个区间Ai```Aj求和
    */
    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    usingnamespace std;
    constint MAXN=100000;
    int num[MAXN];
    struct Node
    {
        int l,r;//区间的左右端点
        longlong nSum;//区间上的和
        longlong Inc;//区间增量的累加
    } segTree[MAXN*3];
    void Build(int i,int l,int r)
    {
        segTree[i].l=l;
        segTree[i].r=r;
        segTree[i].Inc=0;
        if(l==r)
        {
            segTree[i].nSum=num[l];
            return;
        }
        int mid=(l+r)>>1;
        Build(i<<1,l,mid);
        Build(i<<1|1,mid+1,r);
        segTree[i].nSum=segTree[i<<1].nSum+segTree[i<<1|1].nSum;
    }
    void Add(int i,int a,int b,long long c)//在结点i的区间(a,b)上增加c
    {
        if(segTree[i].l==a&&segTree[i].r==b)
        {
            segTree[i].Inc+=c;
            return;
        }
        segTree[i].nSum+=c*(b-a+1);
        int mid=(segTree[i].l+segTree[i].r)>>1;
        if(b<=mid)  Add(i<<1,a,b,c);
        elseif(a>mid)  Add(i<<1|1,a,b,c);
        else
        {
            Add(i<<1,a,mid,c);
            Add(i<<1|1,mid+1,b,c);
        }
    }
    longlong Query(int i,int a,int b)//查询a-b的总和
    {
        if(segTree[i].l==a&&segTree[i].r==b){
            return segTree[i].nSum+(b-a+1)*segTree[i].Inc;
        }
        segTree[i].nSum+=(segTree[i].r-segTree[i].l+1)*segTree[i].Inc;
        int mid=(segTree[i].l+segTree[i].r)>>1;
        Add(i<<1,segTree[i].l,mid,segTree[i].Inc);
        Add(i<<1|1,mid+1,segTree[i].r,segTree[i].Inc);
        segTree[i].Inc=0;
        if(b<=mid) 
            return Query(i<<1,a,b);
        else if(a>mid) 
            return Query(i<<1|1,a,b);
        else
            return Query(i<<1,a,mid)+Query(i<<1|1,mid+1,b);
    }
    int main()
    {
        int n,q;
        int i;
        int a,b,c;
        char ch;
        while(scanf("%d%d",&n,&q)!=EOF)
        {
            for(i=1; i<=n; i++)  scanf("%d",&num[i]);
            Build(1,1,n);
            for(i=1; i<=q; i++)
            {
                cin>>ch;
                if(ch=='C')
                {
                    scanf("%d%d%d",&a,&b,&c);
                    Add(1,a,b,c);
                }
                else
                {
                    scanf("%d%d",&a,&b);
                    printf("%I64d
    ",Query(1,a,b));
                }
            }
        }
        return0;
    }
  • 相关阅读:
    正式定居博客圆,发些以前在Topcoder上的练习题,对算法和STL有兴趣的朋友可以看下:)
    TopCoder真题讲解之二
    “命名空间“System”中不存在类型或命名空间名称“Linq”(是缺少程序集引用吗?)”
    短信发送
    JavaScript打印和预览等
    .net获取IP地址的几种方法转载
    WinForm中控件与背景透明
    用C#实现C/S模式下软件自动在线升级转
    Microsoft Access 时间函数汇总
    .net 发送Email 单发 群发
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/5225955.html
Copyright © 2020-2023  润新知