zoukankan      html  css  js  c++  java
  • HAOI2012 高速公路

    题目传送门

    不开long long见祖宗系列


    很自然的想法是求出所有区间的价值然后除区间个数

    怎么求区间价值?
    设数(x)的位置为(p),则(x)([l,r])中所有区间的价值做出了((r−p+1) imes (p−l+1))次贡献(乘法原理)
    将这个式子拆开,就是((r−l+1−r imes l) imes x imes p^2+(r+l) imes x imes p − x)

    然后用线段树维护一下(x imes p ^ 2 , x imes p)(x)就可以了

    最后将这个值除以区间个数就好了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    #define ls p << 1
    #define rs p << 1 | 1
    #define mid ((l + r) >> 1)
    using namespace std;
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
            k = k * 10 + c -48, c = getchar();
        return k * f;
    }
    char read_c() {
        char c = getchar();
        while(c != 'C' && c != 'Q') c = getchar();
        return c;
    }
    LL calc(bool opt, LL l, LL r) {
        if(opt) // 维护 x*p
            return (l+r) * (r-l+1) / 2;
        else {
            l -= 1; // 维护 x*p*p
            return (r * (r+1) * ((r<<1)+1) / 6) - (l * (l+1) * ((l<<1)+1) / 6);
        }
    }
    struct zzz {
        LL s1, s2, s3;
        void operator += (const zzz &y) & { //重载运算符,可以直接用 += 相加
            s1 += y.s1, s2 += y.s2, s3 += y.s3;
            return ;
        }
    }tree[100010 << 2];
    LL tag[100010 << 2];
    void up(LL p) {
        tree[p].s1 = tree[ls].s1 + tree[rs].s1;
        tree[p].s2 = tree[ls].s2 + tree[rs].s2;
        tree[p].s3 = tree[ls].s3 + tree[rs].s3;
    }
    void down(LL p, LL l, LL r) {
        LL k = tag[p];
        tree[ls].s1 += (mid-l+1) * k;
        tree[ls].s2 += calc(1, l, mid) * k;
        tree[ls].s3 += calc(0, l, mid) * k;
    
        tree[rs].s1 += (r-mid) * k;
        tree[rs].s2 += calc(1, mid+1, r) * k;
        tree[rs].s3 += calc(0, mid+1, r) * k;
    
        tag[ls] += k; tag[rs] += k; tag[p] = 0;
    }
    void update(LL l, LL r, LL p, LL nl, LL nr, LL k) {
        if(nl <= l && nr >= r) {
            tree[p].s1 += (r-l+1) * k;
            tree[p].s2 += calc(1, l, r) * k;
            tree[p].s3 += calc(0, l, r) * k;
            tag[p] += k; return ;
        }
        down(p, l, r);
        if(nl <= mid) update(l, mid, ls, nl, nr, k);
        if(nr > mid) update(mid+1, r, rs, nl, nr, k);
        up(p);
    }
    zzz query(LL l, LL r, LL p, LL nl, LL nr) {
        zzz ans = (zzz){0, 0, 0};
        if(nl <= l && nr >= r)
            return tree[p];
        down(p, l, r);
        if(nl <= mid)
            ans += query(l, mid, ls, nl, nr);
        if(nr > mid)
            ans += query(mid+1, r, rs, nl, nr);
        up(p);
        return ans;
    }
    LL gcd(LL x, LL y) {
        return x % y == 0 ? y : gcd(y, x % y);
    }
    int main() {
        LL n = read(), m = read();
        for(LL i = 1; i <= m; ++i) {
            char opt = read_c(); LL l = read(), r = read() - 1;
            if(opt == 'C') {
                LL k = read();
                update(1, n, 1, l, r, k);
            }
            else {
                zzz x = query(1, n, 1, l, r);
                LL ans = (r-l+1-r*l) * x.s1 + (r+l) * x.s2 - x.s3;
                LL b = (r-l+2) * (r-l+1) / 2;
                LL g = gcd(ans, b); //约分
                printf("%lld/%lld
    ", ans/g, b/g);
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    nginx 转发配置
    Rancher中httpd证书的管理和使用
    JDK-docker
    软路由
    rancher相关
    rancher部署
    电商 好文 知识积累
    SpringBlade 接口文档 请求token接口报错
    SpringBlade 接口文档 无法访问
    电商 好文
  • 原文地址:https://www.cnblogs.com/morslin/p/11855243.html
Copyright © 2011-2022 走看看