0w1

UVA 12086 Potentiometers ( 平方分割 Range Sum Query )

UVa Online Judge
Range Sum Query の基礎問題を平方分割で処理した。
ncastar.hatenablog.com
この記事が大変参考になりました。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;

int kase;
int n;
int a[ MAXN ];

int BS;
vector< int > bucket;

void init(){
    bucket.clear();
    BS = sqrt( n ) + 1;
    int sum = 0, cnt = 0;
    for(int i = 0; i < n; ++i){
        sum += a[ i ];
        ++cnt;
        if( cnt == BS ){
            cnt = 0;
            bucket.push_back( sum );
            sum = 0;
        }
    }
    if( cnt ) bucket.push_back( sum );
}

void update(int k, int x){
    int bk = k / BS;
    bucket[ bk ] -= a[ k ];
    bucket[ bk ] += x;
    a[ k ] = x;
}

int qsum(int ql, int qr){
    int bl = ql / BS;
    int br = qr / BS;
    int res = 0;
    if( bl == br ){ // needs extra care
        for(int i = ql; i <= qr; ++i)
            res += a[ i ];
    } else{
        int lt = ( bl + 1 ) * BS;
        for(int i = ql; i < lt; ++i)
            res += a[ i ];
        int rs = br * BS;
        for(int i = rs; i <= qr; ++i)
            res += a[ i ];
        for(int i = bl + 1; i < br; ++i)
            res += bucket[ i ];
        
    }
    return res;
}

int main(){
    while( scanf("%d", &n) == 1 && n ){
        for(int i = 0; i < n; ++i)
            scanf("%d", a + i);
        if( kase ) puts("");
        printf("Case %d:\n", ++kase);
        init();
        while( true ){
            char op[ 10 ]; scanf("%s", op);
            if( op[ 0 ] == 'E' ) break;
            int x, y; scanf("%d%d", &x, &y);
            if( op[ 0 ] == 'S' ) update( --x, y );
            else printf("%d\n", qsum( --x, --y ));
        }
    }
    return 0;
}