zoukankan      html  css  js  c++  java
  • 链上二次求和

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int MAXN = 202020;
    const int MOD = 1000000007;
    const int REV2 = (MOD + 1) / 2;
    const int REV6 = (MOD + 1) / 6;
    inline int get_polynomial_sum(int a0, int a1, int a2, int x)
    {
        return (((long long)a2 * (2 * x + 1) % MOD * REV6 + (long long)a1 * REV2) % MOD * (x + 1) + a0) % MOD * x % MOD;
    }
    int n, m, a[MAXN];
    class Segment_tree
    {
    public:
        int st, ed;
        Segment_tree *l, *r;
        int sum;
        int a[3];//lazy tags
        //a[0]: add 1, 1, 1, 1, ...
        //a[1]: add 1, 2, 3, 4, ...
        //a[2]: add 1, 4, 9, 16, ...
        Segment_tree(int st, int ed): st(st), ed(ed), l(0), r(0), sum(0)
        {
            a[0] = a[1] = a[2] = 0;
        }
        Segment_tree(int st, int ed, Segment_tree *l, Segment_tree *r): st(st), ed(ed), l(l), r(r)
        {
            a[0] = a[1] = a[2] = 0;
            update();
        }
        int len() const
        {
            return ed - st + 1;
        }
        void add(int b0, int b1, int b2)
        {
            a[0] = (a[0] + b0) % MOD;
            a[1] = (a[1] + b1) % MOD;
            a[2] = (a[2] + b2) % MOD;
            sum = (sum + get_polynomial_sum(b0, b1, b2, len())) % MOD;
        }
        void down()
        {
            if(!a[0] && !a[1] && !a[2])
                return;
            l->add(a[0], a[1], a[2]);
            int llen = l->len();
            r->add((((long long)a[2] * llen + a[1]) % MOD * llen + a[0]) % MOD, ((long long)a[2] * llen * 2 + a[1]) % MOD, a[2]);
            a[0] = a[1] = a[2] = 0;
        }
        void update()
        {
            sum = (l->sum + r->sum) % MOD;
        }
    };
    Segment_tree *root;
    Segment_tree *build(int st, int ed)
    {
        return st == ed ? new Segment_tree(st, ed) : new Segment_tree(st, ed, build(st, (st + ed) >> 1), build(((st + ed) >> 1) + 1, ed));
    }
    long long query(Segment_tree *p, int st, int ed)
    {
        if(p->st >= st && p->ed <= ed)
            return p->sum;
        p->down();
        if(ed <= p->l->ed)
            return query(p->l, st, ed);
        if(st >= p->r->st)
            return query(p->r, st, ed);
        return query(p->l, st, ed) + query(p->r, st, ed);
    }
    void add(Segment_tree *p, int st, int ed, int b0, int b1, int b2)
    {
    //    if(p == root)
    //        printf("add: [%d, %d] %d + %dx + %dx^2
    ", st, ed, b0, b1, b2);
        if(p->st >= st && p->ed <= ed)
        {
            p->add(b0, b1, b2);
            return;
        }
        p->down();
        if(ed <= p->l->ed)
            add(p->l, st, ed, b0, b1, b2);
        else if(st >= p->r->st)
            add(p->r, st, ed, b0, b1, b2);
        else
        {
            add(p->l, st, p->l->ed, b0, b1, b2);
            int llen = p->l->ed - st + 1;
            add(p->r, p->r->st, ed, (((long long)b2 * llen + b1) % MOD * llen + b0) % MOD, ((long long)b2 * llen * 2 + b1) % MOD, b2);
        }
        p->update();
    }
    void change(int u, int v, int d)
    {
        if(u > v)
            swap(u, v);
        int len = v - u + 1;
        v = n - v + 1;
        add(root, 1, n, 0, (long long)len * d % MOD, 0);
        if(u + 1 <= n)
            add(root, u + 1, n, 0, (long long)(MOD - d) * REV2 % MOD, (long long)(MOD - d) * REV2 % MOD);
        if(u + len + 1 <= n)
            add(root, u + len + 1, n, 0, (long long)d * REV2 % MOD, (long long)d * REV2 % MOD);
        if(v + 1 <= n)
            add(root, v + 1, n, 0, (long long)(MOD - d) * REV2 % MOD, (long long)(MOD - d) * REV2 % MOD);
        if(v + len + 1 <= n)
            add(root, v + len + 1, n, 0, (long long)d * REV2 % MOD, (long long)d * REV2 % MOD);
    }
    int main()
    {
    //    freopen("sum.in", "r", stdin);
    //    freopen("sum.out", "w", stdout);
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        root = build(1, n);
        for(int i = 1; i <= n; i++)
            if(a[i])
                change(i, i, a[i]);
        for(int i = 1; i <= m; i++)
        {
            int tp, u, v, d;
            scanf("%d%d%d", &tp, &u, &v);
            if(tp == 1)
            {
                scanf("%d", &d);
                change(u, v, d);
            }
            else
            {
                printf("%d
    ", (int)(query(root, u, v) % MOD));
            }
        }
        return 0;
    }
  • 相关阅读:
    北京大学计算机系2009应试硕士生上机考试(DF)
    我的考研2010(一)
    这张容易看懂...
    关于招商银行信用卡的若干事宜
    20 years
    C/C++中关于qsort的使用
    有道破题~~
    POJ 4010 2011
    有道难题练习赛 Sibonacci
    北京大学计算机系2009应试硕士生上机考试(AC)
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/8966682.html
Copyright © 2011-2022 走看看