HDU A Simple Problem with Integers

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个数字A1,A2...An,然后会进行两种操作

操作1:a b k c表示a<=i<=b中(i-a)%k == 0就加c。

操作2:a 查询A[a]的值。

此题我用线段写了一遍,本以为维护左边界和取余值就可以了,但是一直错(水平不够吧),

然后看了一下题解,因为k<=10,所以取余k的余数种数最多55种,所以可以用一个二维

数组用树状数组维护,将a%k映射为(k-1)*10+a%k,这样保证不同k的不同余数的下标值唯一,

然后将a更新c,将b+1更新为-c,这样保证求前缀和的时候如果在[a,b]内就会加c,不在就不会加,

然后是为什么可以直接查询在[a,b]间就加呢?因为如果a%k == b%k,那么(b-a)%k == 0,

映射a的时候是(i-1)*10+a%i就保证余数相等了,就只需要考虑在不在更新的区间内就行了。

#include <stdio.h>
#include <string.h>
const int maxn = 50005;
int sum[100][maxn], A[maxn], n;
inline int lowbit ( int x ) { return x & -x; }
void add ( int k, int x, int v )
{
    while ( x <= n )
    {
        sum[k][x] += v;
        x += lowbit ( x );
    }
}
int bit_sum ( int x )
{
    int res = 0;
    for ( int i = 1; i <= 10; i ++ )
    {
        //a%k == b%k  -->  ( b-a )%k == 0
        //所以只需要知道在区间更新的值为多少
        int k = ( i-1 )*10+x%i; //所有起始位置余数为x%i的和
        for ( int j = x; j > 0; j -= lowbit ( j ) )
            res += sum[k][j];
    }
    return res+A[x];
}
void solve ( )
{
    while ( ~ scanf ( "%d", &n ) )
    {
        memset ( sum, 0, sizeof ( sum ) );
        for ( int i = 1; i <= n; i ++ )
            scanf ( "%d", &A[i] );
        int q, op, a, b, k, c;
        scanf ( "%d", &q );
        while ( q -- )
        {
            scanf ( "%d", &op );
            if ( op == 1 )
            {
                scanf ( "%d%d%d%d", &a, &b, &k, &c );
                add ( 10*( k-1 )+a%k, a, c );   //将余数映射到下标
                add ( 10*( k-1 )+a%k, b+1, -c );
            }
            else
            {
                scanf ( "%d", &a );
                printf ( "%d\n", bit_sum ( a ) );
            }
        }
    }
}
int main ( )
{
    solve ( );
    return 0;
}


你可能感兴趣的:(HDU A Simple Problem with Integers)