zoukankan      html  css  js  c++  java
  • C

    题意:有一个比较长的区间可能是100000.长度, 每个点都有一个值(值还比较大),现在有一些操作,C abc, 把区间a-b内全部加上c, Qab,求区间ab的值。

    分析:很明显我们不可能对区间的每个点都进行更新,不过我们可以使用一个op的开关,如果op等于0说明这个不需要更新,如果等于1就说明需要进行更新,这样只需要和插入的时候进行一下更新即可
    ***********************************************************************
    注意:在向下更新的时候如果是更新子树有可能一个区间会更新多次,而子树区间更新的时候不能乘本区间的更新值,只能乘根节点的更新值,根节点的跟新值用完后归0;
     
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;

    #define maxn 100005
    #define Lson root<<1,L,tree[root].Mid()
    #define Rson root<<1|1,tree[root].Mid()+1,R

    struct Tree//op等于0的时候子树不需要更新,op等于1需要更新
    {
        int L, R, op;//需要向下更新的值为e
        long long sum, e;//因为区间和比较大,所以使用long long 保存
        int Mid(){return (L+R)/2;}
        int Len(){return (R-L+1);}
    }tree[maxn*4];
    long long val[maxn];

    void Down(int root)//向下更新
    {
        if(tree[root].op && tree[root].L != tree[root].R)
        {
            tree[root].op = false;
            tree[root<<1].op = tree[root<<1|1].op = true;
            tree[root<<1].e += tree[root].e;
            tree[root<<1|1].e += tree[root].e;

            tree[root<<1].sum += tree[root<<1].Len() * tree[root].e;
            tree[root<<1|1].sum += tree[root<<1|1].Len() * tree[root].e;

            tree[root].e = 0;
        }
    }
    void Build(int root, int L, int R)
    {
        tree[root].L = L, tree[root].R = R;
        tree[root].op = false;

        if(L == R)
        {
            tree[root].sum = val[L];
            return ;
        }

        Build(Lson);
        Build(Rson);

        tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
    }
    void Insert(int root, int L, int R, long long e)
    {
        Down(root);

        tree[root].sum += (R-L+1) * e;

        if(tree[root].L == L && tree[root].R == R)
        {
            tree[root].e = e, tree[root].op = true;
            return ;
        }

        if(R <= tree[root].Mid())
            Insert(root<<1, L, R, e);
        else if(L > tree[root].Mid())
            Insert(root<<1|1, L, R, e);
        else
        {
            Insert(Lson, e);
            Insert(Rson, e);
        }
    }
    long long Query(int root, int L, int R)
    {
        Down(root);

        if(tree[root].L == L && tree[root].R == R)
            return tree[root].sum;
        if(R <= tree[root].Mid())
            return Query(root<<1, L, R);
        else if(L > tree[root].Mid())
            return Query(root<<1|1, L, R);
        else
            return Query(Lson) + Query(Rson);
    }

    int main()
    {
        int i, N, Q;

        while(scanf("%d%d", &N, &Q) != EOF)
        {
            for(i=1; i<=N; i++)
                scanf("%I64d", &val[i]);
            Build(11, N);

            int a, b; char s[10];
            long long c;

            while(Q--)
            {
                scanf("%s%d%d", s, &a, &b);

                if(s[0] == 'C')
                {
                    scanf("%I64d", &c);
                    Insert(1, a, b, c);
                }
                else
                {
                    long long ans = Query(1, a, b);
                    printf("%I64d ", ans);
                }
            }
        }

        return 0;
    }

    /*
    5 2
    1 2 3 4 5
    C 1 5 5
    Q 1 1
    */
  • 相关阅读:
    2018.6.8 现代企业管理复习总结
    写时复制
    字符串类示例
    信号量示例
    对象赋值的语义
    对象复制的语义
    无用单元和悬挂引用
    初始化
    静态数据成员,静态成员函数
    同时找出最大数和最小数
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4677658.html
Copyright © 2011-2022 走看看