zoukankan      html  css  js  c++  java
  • bzoj2752

    线段树+概率

    今天这道题爆零了,奥妙重重。

    其实我们可以把式子化成这样:sigma((i-l+1)*(r-i+1)*ai) 这里r减了1

    然后展开,(1-l)*(r+1)*ai+(r+l)*i*ai-i*i*ai

    我们发现除了含有i的项其他都可以提到外面,也就是说我们要维护ai,i*ai,i*i*ai三个量。

    那么就用线段树维护,打标记时用数列公式即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 100010;
    int n, m;
    struct seg {
        ll tag[N << 2], tree[N << 2][4];
        void pushdown(int x, int l, int r)
        {
            if(!tag[x]) return;
            tag[x << 1] += tag[x];
            tag[x << 1 | 1] += tag[x];
            int mid = (l + r) >> 1;
            tree[x << 1][1] += tag[x] * (ll)(mid - l + 1ll);
            tree[x << 1 | 1][1] += tag[x] * (ll)(r - mid);
            tree[x << 1][2] += tag[x] * (ll)(l + mid) * (ll)(mid - l + 1) / 2ll;
            tree[x << 1 | 1][2] += tag[x] * (ll)(r + mid + 1ll) * (ll)(r - mid) / 2ll;
            tree[x << 1][3] += tag[x] * ((ll)mid * (ll)(mid + 1ll) * (ll)(2ll * mid + 1ll) - (ll)(l - 1ll) * (ll)l * (ll)(2ll * l - 1ll)) / 6ll;
            tree[x << 1 | 1][3] += tag[x] * ((ll)r * (ll)(r + 1ll) * (ll)(2ll * r + 1ll) - (ll)mid * (ll)(mid + 1ll) * (ll)(2ll * mid + 1ll)) / 6ll;
            tag[x]= 0ll;
        }
        void update(int l, int r, int x, int a, int b, ll delta)
        {
            if(l > b || r < a) return;
            if(l >= a && r <= b)
            {
                tag[x] += delta;
                tree[x][1] += (ll)(r - l + 1ll) * delta;
                tree[x][2] += (ll)(l + r) * (ll)(r - l + 1) / 2ll * delta;
                tree[x][3] += ((ll)r * (ll)(r + 1ll) * (2ll * r + 1) - (ll)(l - 1ll) * (ll)l * (ll)(2ll * l - 1ll)) / 6ll * delta;
                return;
            }
            pushdown(x, l, r);
            int mid = (l + r) >> 1;
            update(l, mid, x << 1, a, b, delta);
            update(mid + 1, r , x << 1 | 1, a, b, delta);
            for(int i = 1; i <= 3; ++i)
                tree[x][i] = tree[x << 1][i] + tree[x << 1 | 1][i];
        }
        ll query(int l, int r, int x, int a, int b, int type)
        {
            if(l > b || r < a) return 0ll;
            if(l >= a && r <= b) return tree[x][type];
            pushdown(x, l, r);
            int mid = (l + r) >> 1;
            return (query(l, mid, x << 1, a, b, type) + (query(mid + 1, r, x << 1 | 1, a, b, type)));
        }
    } t;
    ll gcd(ll a, ll b)
    {
        return !b ? a : gcd(b, a % b); 
    }
    int main()
    {
    //    freopen("c.in", "r", stdin);
    //    freopen("c.out", "w", stdout);
        scanf("%d%d", &n, &m);
        --n;
        while(m--)
        {
            char s[10]; int l, r; ll delta; scanf("%s", s);
            if(s[0] == 'C')
            {
                scanf("%d%d%lld", &l , &r, &delta);
                --r;
                t.update(1, n, 1, l, r, delta);
            }
            if(s[0] == 'Q')
            {
                scanf("%d%d", &l, &r);
                --r;
                ll T1 = t.query(1, n, 1, l, r, 1);
                ll T2 = t.query(1, n, 1, l, r, 2);
                ll T3 = t.query(1, n, 1, l, r, 3);
                ll ans = (ll)(1ll - l) * (ll)(r + 1ll) * T1 + (ll)(r + l) * T2 - T3;
                ll T4 = (ll)(r - l + 2ll) * (ll)(r - l + 1ll) / 2ll;
                ll T = gcd(ans, T4);
                printf("%lld/%lld
    ", ans / T, T4 / T);
            }
        }
    //    fclose(stdin); fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    童年
    转:如何破解超星打印页数限制
    2016.7.14.2014noip模拟赛D1(网上貌似搜不到
    商店购物
    几道有趣的题
    2016.7.11.第27套测试题(noip2013提D1)
    2016.7.12.第28套测试题(2013noip题D2)
    跨域访问http接口的使用
    心得之——程序的修改和拓展
    不使用<script>导入js文件
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7070871.html
Copyright © 2011-2022 走看看