• HDU 4267 A Simple Problem with Integers


    方法参考http://blog.csdn.net/acm_cxlove/article/details/7854526

    题目:给出n个数,每次将一段区间内满足(i-l)%k==0 (r>=i>=l) 的数ai增加c
    http://acm.hdu.edu.cn/showproblem.php?pid=4267
    比较容易往线段树上想的。但是由于更新的是一些离散的点,比较麻烦
    可以考虑这些点的共性,总是隔几个,更新一个,那我们把区间内的数关于k的余数分组
    这样每次更新的都是其中的一组,而且是连续的。
    由于 K比较小,这是本题的突破口,那么关于k的余数情况,最多只有55种。
    即如果k=1,则分为1组,k=2分为2组……
    一开始傻叉了打算维护55棵线段树,其实也是可以的,更新只需要1棵,查询是10棵,还是可以接受的。
    不过只需要在线段树结点维护这55种情况即可。
    不过内存比较紧,要把所有的情况压缩一下,不能开10*10的空间。
    同样更新只需要一个,最终统计的话,需要遍历所有的K,也就是最多是10.


    自己太水了,有些技巧的线段树现在还是想不出,知识量太少了


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    # define MAX 51111
    # define ll(x) x << 1
    # define rr(x) x << 1 | 1
    using namespace std;
    
    struct node {
        int l,r,sum,mid;
        int add[55]; //关于k的余数情况,最多只有55种
    }tree[MAX*4];
    int a[MAX],n,cnt[11][11];
    
    void build (int l,int r,int num) {
        tree[num].l = l;
        tree[num].r = r;
        tree[num].mid = (l + r) >> 1;
        memset(tree[num].add,0,sizeof(tree[num].add));
        tree[num].sum = 0;
        if(l == r)
            return ;
        build(l,tree[num].mid ,ll(num));
        build(tree[num].mid + 1,r,rr(num));
    }
    
    void up(int num) {
        tree[num].sum = tree[ll(num)].sum + tree[rr(num)].sum;
    }
    
    void down(int num) {
        if(tree[num].sum != 0) {
            tree[ll(num)].sum += tree[num].sum;
            tree[rr(num)].sum += tree[num].sum;
            tree[num].sum = 0;
            for(int i=0; i<55; i++) {
                tree[ll(num)].add[i] += tree[num].add[i];
                tree[rr(num)].add[i] += tree[num].add[i];
                tree[num].add[i] = 0;
            }
        }
    }
    
    void update(int l,int r,int num,int mod,int j, int dsum) {
        if(l <= tree[num].l && r >= tree[num].r) {
            tree[num].add[cnt[mod][j]] += dsum;
            tree[num].sum += dsum;
            return ;
        }
        down(num);
        if(r <= tree[num].mid ) update (l,r,ll(num),mod,j,dsum);
        else if(l > tree[num].mid) update(l,r,rr(num),mod,j,dsum);
        else {
            update(l,tree[num].mid,ll(num),mod,j,dsum);
            update(tree[num].mid+1,r,rr(num),mod,j,dsum);
        }
        up(num);
    }
    
    int query(int num,int j) {
        if(tree[num].l == tree[num].r) {
            int tmp = a[tree[num].l];
            for(int i=1; i<=10; i++) tmp += tree[num].add[cnt[i][j%i]] ;
            return tmp;
        }
        down(num);
        if(j <= tree[num].mid) return query(ll(num),j);
        else return query(rr(num),j);
    }
    
    int main() {
        int i,m;
        int p,q,r,s,t;
        int tmp = 0;
        for(i=1; i<=10; i++)
            for(int j=0; j<i; j++) cnt[i][j] = tmp++;
        while(cin >> n) {
            for(i=1; i<=n; i++) {
                scanf("%d",&a[i]);
            }
            build(1,n,1);
            cin >> m;
            for(i=1; i<=m; i++) {
                scanf("%d",&p);
                if(p == 2) {
                    scanf("%d",&q);
                    printf("%d
    ",query(1,q));
                }
                else {
                    scanf("%d%d%d%d",&q,&r,&s,&t);
                    update(q,r,1,s,q % s,t);
                }
            }
        }
        return 0;
    }


  • 相关阅读:
    dict
    list & tuple
    int & bool & string
    关于gcc内置的原子操作函数
    关于quicklz压缩算法在游戏中的应用
    为mingw生成mysql的客户端库文件
    linux下core生成与调试
    linux下GCC编译动态库切记加 -fPIC
    一则gvim命令
    WIN系统下网络莫名其妙怪异的无法可用时的处理方式
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3225954.html
Copyright © 2020-2023  润新知