zoukankan      html  css  js  c++  java
  • POJ 3468:A Simple Problem with Integers(线段树[成段更新])

    题意:N个数Q次操作。一共两种操作:Q l r :询问[l,r]这个区间里的数字和,C l r c: [l,r]区间里的每个数都加上c。1 ≤ N,Q ≤ 100000.

    方法:线段树的成段更新。注意懒惰标记。这只是为了有个模板。易错点在代码中以下划线标注。

    //16:06
    #include <cstdio>
    #include <cstring>
    #define N 100010
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    
    long long sum[N<<2];
    long long col[N<<2];//一直WA,只因这里写成Int。这个和上面那个要同个类型才是。
    
    void pushUp(int rt) {
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void pushDown(int len, int rt) {
        if (col[rt]) {
            col[rt<<1] += col[rt];
            col[rt<<1|1] += col[rt];
            sum[rt<<1] += (len-len/2)*col[rt];
            sum[rt<<1|1] += (len/2)*col[rt];
            col[rt] = 0;
        }
    }
    
    void build(int l, int r, int rt) {
        col[rt] = 0;
    if (l==r) {
            scanf("%lld", &sum[rt]);
            return;
        }
        int mid = (l+r)/2;
        build(lson);
        build(rson);
        pushUp(rt);
    }
    
    void update(int L, int R, int v, int l, int r, int rt) {
        if (L <= l && r <= R) {
            col[rt] += v;
            sum[rt] += (r-l+1ll)*v;
            return;
        }
        pushDown(r-l+1, rt);
        int mid = (l+r)/2;
        if (L <= mid) update(L,R,v,lson);
        if (R > mid) update(L,R,v,rson);
        pushUp(rt);
    }
    
    long long query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) {
            return sum[rt];
        }
        pushDown(r-l+1,rt);
        int mid = (l+r)/2;
        long long ans = 0;
        if (L <= mid) ans += query(L,R,lson);
        if (R > mid) ans += query(L,R,rson);
        return ans;
    }
    
    
    int main() {
        int n, q;
        while (scanf("%d%d", &n, &q) != EOF) {
            build(1,n,1);
            for (int i = 0; i < q; i++) {
                char com[20];
                scanf("%s", com);
                if (com[0] == 'Q') {
                    int l, r = 0;
                    scanf("%d%d", &l, &r);
                    //printf("query %d %d
    ", l, r);
                    printf("%lld
    ", query(l,r,1,n,1));
                } else if (com[0] == 'C') {
                    int l, r, add;
                    scanf("%d%d%d", &l, &r, &add);
                    update(l,r,add,1,n,1);
                }
            }
        }
        return 0;
    }

    另外感觉三个函数有很多重复点,写了一个紧凑版本,不过看起来代码量差不多,而且效率低了呢。

    //16:06
    #include <cstdio>
    #include <cstring>
    #define N 100010
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    
    long long sum[N<<2];
    long long col[N<<2];
    
    void pushUp(int rt) {
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void pushDown(int len, int rt) {
        if (col[rt]) {
            col[rt<<1] += col[rt];
            col[rt<<1|1] += col[rt];
            sum[rt<<1] += (len-len/2)*col[rt];
            sum[rt<<1|1] += (len/2)*col[rt];
            col[rt] = 0;
        }
    }
    
    long long basicDo(bool isBuild, int L, int R, int v, int l, int r, int rt) {
        if (isBuild) col[rt] = 0;
        if (l == r || L <= l && r <= R) {
            if (isBuild) scanf("%lld", &sum[rt]);
            col[rt] += v;
            sum[rt] += (r-l+1ll)*v;
            return sum[rt];
        }
        pushDown(r-l+1, rt);
        int mid = (l+r)/2;
        long long ans = 0;
        if (isBuild || L<= mid) ans += basicDo(isBuild,L,R,v,lson);
        if (isBuild || R > mid) ans += basicDo(isBuild,L,R,v,rson);
        pushUp(rt);
        return ans;
    }
    void build(int l, int r, int rt) {
        basicDo(true, 0,0,0,l,r, rt);
    }
    void update(int L, int R, int v, int l, int r, int rt) {
        basicDo(false, L, R, v, l, r, rt);
    }
    long long query(int L, int R, int l, int r ,int rt) {
        return basicDo(false, L, R, 0, l, r, rt);
    }
    
    
    int main() {
        int n, q;
        while (scanf("%d%d", &n, &q) != EOF) {
            build(1,n,1);
            for (int i = 0; i < q; i++) {
                char com[20];
                scanf("%s", com);
                if (com[0] == 'Q') {
                    int l, r = 0;
                    scanf("%d%d", &l, &r);
                    //printf("query %d %d
    ", l, r);
                    printf("%lld
    ", query(l,r,1,n,1));
                } else if (com[0] == 'C') {
                    int l, r, add;
                    scanf("%d%d%d", &l, &r, &add);
                    update(l,r,add,1,n,1);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Android 高仿微信支付密码输入控件
    ListView用法总结
    我的感悟
    Android Scroll分析——滑动效果产生
    如何查看Android的Keystore文件的SHA1值
    Android 事件拦截机制一种粗鄙的解释
    Android 自定义ViewGroup
    Android 自定义View 总结
    Android 自定义View 三板斧之三——重写View来实现全新控件
    Android 自定义View 三板斧之二——组合现有控件
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3611873.html
Copyright © 2011-2022 走看看