• POJ 3468 A Simple Problem with Integers


    POJ_3468

        现在用的方法还是比较慢的,因为YTQ给我那个PPT还没深入研究透,PPT上面对这种的题的解法是用维护前缀和的前缀和以及{n*An}的前缀和来实现的,而我用的方法就是比较朴素的做lazy标记,来标识该区间内每个元素增加了多少。如果需要查询子区间时,再更新子区间的和,并将lazy标记传递下去。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 100010
    int N, M, Q;
    long long int tree[4 * MAXD], lazy[4 * MAXD], res;
    int left[4 * MAXD], right[4 * MAXD], num[4 * MAXD];
    char op[5];
    void init()
    {
    int i, j;
    for(M = 1; M < N + 2; M <<= 1);
    memset(tree, 0, sizeof(tree));
    memset(lazy, 0, sizeof(lazy));
    for(i = 0, j = M + 1; i < N; i ++, j ++)
    scanf("%lld", &tree[j]);
    for(i = M, j = 0; i < 2 * M; i ++, j ++)
    {
    left[i] = right[i] = j;
    if(j >= 1 && j <= N)
    num[i] = 1;
    else
    num[i] = 0;
    }
    for(i = M - 1; i > 0; i --)
    {
    tree[i] = tree[2 * i] + tree[2 * i + 1];
    num[i] = num[2 * i] + num[2 * i + 1];
    left[i] = left[2 * i];
    right[i] = right[2 * i + 1];
    }
    }
    void add(int cur, int &a, int &b, int &c)
    {
    int i, k;
    if(lazy[cur] && cur < M)
    {
    lazy[2 * cur] += lazy[cur];
    lazy[2 * cur + 1] += lazy[cur];
    tree[2 * cur] += lazy[cur] * num[2 * cur];
    tree[2 * cur + 1] += lazy[cur] * num[2 * cur + 1];
    lazy[cur] = 0;
    }
    if(left[cur] >= a && right[cur] <= b)
    {
    k = c * num[cur];
    tree[cur] += k;
    lazy[cur] = c;
    for(i = cur; i ^ 1; i >>= 1)
    tree[i >> 1] += k;
    return ;
    }
    if(left[2 * cur] <= b && right[2 * cur] >= a)
    add(2 * cur, a, b, c);
    if(left[2 * cur + 1] <= b && right[2 * cur + 1] >= a)
    add(2 * cur + 1, a, b, c);
    }
    void make(int cur, int &a, int &b)
    {
    int i, k;
    if(lazy[cur] && cur < M)
    {
    lazy[2 * cur] += lazy[cur];
    lazy[2 * cur + 1] += lazy[cur];
    tree[2 * cur] += lazy[cur] * num[2 * cur];
    tree[2 * cur + 1] += lazy[cur] * num[2 * cur + 1];
    lazy[cur] = 0;
    }
    if(left[cur] >= a && right[cur] <= b)
    {
    res += tree[cur];
    return ;
    }
    if(left[2 * cur] <= b && right[2 * cur] >= a)
    make(2 * cur, a, b);
    if(left[2 * cur + 1] <= b && right[2 * cur + 1] >= a)
    make(2 * cur + 1, a, b);
    }
    void solve()
    {
    int i, j, a, b, c, s, t;
    scanf("%s", op);
    if(op[0] == 'C')
    {
    scanf("%d%d%d", &a, &b, &c);
    add(1, a, b, c);
    }
    else
    {
    scanf("%d%d", &a, &b);
    res = 0;
    make(1, a, b);
    printf("%lld\n", res);
    }
    }
    int main()
    {
    while(scanf("%d%d", &N, &Q) == 2)
    {
    init();
    for(int i = 0; i < Q; i ++)
    solve();
    }
    return 0;
    }


  • 相关阅读:
    类的关联关系
    VisualStudio.DTE 对象可以通过检索 GetService() 方法
    openssl 安装
    反射的效率
    Ascll
    关于JavaScript 原型的理解
    asp.net MVC 学习笔记
    CSS3样式
    List<T>转DataTable
    SQL中的多表联查(SELECT DISTINCT 语句)
  • 原文地址:https://www.cnblogs.com/staginner/p/2230920.html
Copyright © 2020-2023  润新知