hdoj 4267 A Simple Problem with Integers 【线段树】

题目链接:hdoj 4267 A Simple Problem with Integers

A Simple Problem with Integers

Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5030 Accepted Submission(s): 1586

Problem Description
Let A1, A2, … , AN be N elements. You need to deal with two kinds of operations. One type of operation is to add a given number to a few numbers in a given interval. The other is to query the value of some element.

Input
There are a lot of test cases.
The first line contains an integer N. (1 <= N <= 50000)
The second line contains N numbers which are the initial values of A1, A2, … , AN. (-10,000,000 <= the initial value of Ai <= 10,000,000)
The third line contains an integer Q. (1 <= Q <= 50000)
Each of the following Q lines represents an operation.
“1 a b k c” means adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0. (1 <= a <= b <= N, 1 <= k <= 10, -1,000 <= c <= 1,000)
“2 a” means querying the value of Aa. (1 <= a <= N)

Output
For each test case, output several lines to answer all query operations.

Sample Input
4
1 1 1 1
14
2 1
2 2
2 3
2 4
1 2 3 1 2
2 1
2 2
2 3
2 4
1 1 4 2 1
2 1
2 2
2 3
2 4

Sample Output
1
1
1
1
1
3
3
1
2
3
4
1

题意:给定n个元素。有q次操作
1, a b k c 将区间[a, b]里面所有满足(i - a) % k == 0的元素A[i]增加c。
2, a 查询A[a]。

思路:发现k很小,我们可以预处理出以A[s]开头的k连续的所有元素,这些元素是同时增减的。更新的时候找到对应的s和区间[L, R],然后就是区间更新了。查询时累加所有线段树在a位置的元素,结果加上A[a]就好了。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 5*1e4 + 1;
const int MOD = 1e9 + 7;
struct Tree {
    int l, r, sum, lazy;
};
Tree tree[10][10][MAXN<<1], tree1[MAXN<<2];
void PushUp(int o, int k, int s) {
    if(k == 1) {
        tree1[o].sum = tree1[ll].sum + tree1[rr].sum;
    }
    else {
        tree[k-1][s-1][o].sum = tree[k-1][s-1][ll].sum + tree[k-1][s-1][rr].sum;
    }
}
void PushDown(int o, int k, int s) {
    if(k == 1) {
        if(tree1[o].lazy) {
            tree1[ll].lazy += tree1[o].lazy;
            tree1[rr].lazy += tree1[o].lazy;
            tree1[ll].sum += tree1[o].lazy * (tree1[ll].r - tree1[ll].l + 1);
            tree1[rr].sum += tree1[o].lazy * (tree1[rr].r - tree1[rr].l + 1);
            tree1[o].lazy = 0;
        }
        return ;
    }
    k--; s--;
    if(tree[k][s][o].lazy) {
        tree[k][s][ll].lazy += tree[k][s][o].lazy;
        tree[k][s][rr].lazy += tree[k][s][o].lazy;
        tree[k][s][ll].sum += tree[k][s][o].lazy * (tree[k][s][ll].r - tree[k][s][ll].l + 1);
        tree[k][s][rr].sum += tree[k][s][o].lazy * (tree[k][s][rr].r - tree[k][s][rr].l + 1);
        tree[k][s][o].lazy = 0;
    }
}
int a[MAXN];
void Build(int o, int l, int r, int k, int s) {
    if(k == 1) {
        tree1[o].l = l; tree1[o].r = r;
        tree1[o].sum = tree1[o].lazy = 0;
    }
    else {
        tree[k-1][s-1][o].l = l; tree[k-1][s-1][o].r = r;
        tree[k-1][s-1][o].sum = tree[k-1][s-1][o].lazy = 0;
    }
    if(l == r) {
        return ;
    }
    int mid = (l + r) >> 1;
    Build(o<<1, l, mid, k, s); Build(o<<1|1, mid+1, r, k, s);
    PushUp(o, k, s);
}
void Update(int o, int L, int R, int v, int k, int s) {
    if(k == 1) {
        if(tree1[o].l == L && tree1[o].r == R) {
            tree1[o].sum += (tree1[o].r - tree1[o].l + 1) * v;
            tree1[o].lazy += v;
            return ;
        }
    }
    else {
        if(tree[k-1][s-1][o].l == L && tree[k-1][s-1][o].r == R) {
            tree[k-1][s-1][o].sum += (tree[k-1][s-1][o].r - tree[k-1][s-1][o].l + 1) * v;
            tree[k-1][s-1][o].lazy += v;
            return ;
        }
    }
    PushDown(o, k, s); int mid;
    if(k == 1) {
        mid = (tree1[o].l + tree1[o].r) >> 1;
    }
    else {
        mid = (tree[k-1][s-1][o].l + tree[k-1][s-1][o].r) >> 1;
    }
    if(R <= mid) Update(ll, L, R, v, k, s);
    else if(L > mid) Update(rr, L, R, v, k, s);
    else {
        Update(ll, L, mid, v, k, s);
        Update(rr, mid+1, R, v, k, s);
    }
    PushUp(o, k, s);
}
int Query(int o, int pos, int k, int s) {
    if(k == 1) {
        if(tree1[o].l == tree1[o].r) {
            return tree1[o].sum;
        }
    }
    else {
        if(tree[k-1][s-1][o].l == tree[k-1][s-1][o].r) {
            return tree[k-1][s-1][o].sum;
        }
    }
    PushDown(o, k, s); int mid;
    if(k == 1) {
        mid = (tree1[o].l + tree1[o].r) >> 1;
    }
    else {
        mid = (tree[k-1][s-1][o].l + tree[k-1][s-1][o].r) >> 1;
    }
    if(pos <= mid) return Query(ll, pos, k, s);
    else return Query(rr, pos, k, s);
}
int main()
{
    int N;
    while(scanf("%d", &N) != EOF) {
        for(int i = 1; i <= N; i++) {
            scanf("%d", &a[i]);
        }
        for(int k = 1; k <= 10; k++) {
            for(int s = 1; s <= k; s++) {
                Build(1, 1, N / k + 1, k, s);
            }
        }
        int Q; scanf("%d", &Q);
        while(Q--) {
            int op;
            scanf("%d", &op);
            if(op == 1) {
                int x, y, k, d;
                scanf("%d%d%d%d", &x, &y, &k, &d);
                int s = 0;
                for(int i = 1; i <= k; i++) {
                    if((x - i) % k == 0) {
                        s = i; break;
                    }
                }
                int yu = (y - x) % k; y -= yu;
                int L = x / k; int R = y / k;
                if(x % k) L++; if(y % k) R++;
                //cout << L << ' ' << R << endl;
                Update(1, L, R, d, k, s);
            }
            else {
                int v; scanf("%d", &v);
                int ans = 0;
                for(int i = 1; i <= 10; i++) {
                    for(int j = 1; j <= i; j++) {
                        if((v - j) % i == 0) {
                            int pos = v / i;
                            if(v % i) pos++;
                            ans += Query(1, pos, i, j);
                            break;
                        }
                    }
                }
                printf("%d\n", ans + a[v]);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值