hdu 4267 A Simple Problem with Integers 线段树维护不连续点

来源:互联网 发布:图片生成视频软件 编辑:程序博客网 时间:2024/06/06 11:40

题意:给出n个数两种操作, 1,查询第i个数是什么,2,输入a, b, k, c,然后所有满足在区间[a, b]里面的下标i 满足(i - a)% k == 0的全部加上c。

首先可以将每隔k的数看成一堆(如 x , x + k...),对于每堆都可以由线段树维护。那么,需要开多少颗线段树呢,可以这么看,k最大为10,那么 %k = (0, 1, 2, ....k-1 = 9)共有十堆,也可以当k = 1时,%k = 0(第一个),k = 2时,%k = 0, 1(第二,三个)一直到k = 10,%k = (0, 1, 2, 3...9),加起来一共55堆,这里采用的是后者。至于查询,只需要在k = 1~10时分别求和即可。那么怎么确定对那堆数进行维护呢?我们可以对每堆进行编号,从0 一直到54(因为是模嘛),只要确定是那一堆,就可以解决问题了

由 (i - a )% k== 0,转化为i % k == a % k,有a, k已知,则令j = a % k也已知,由于这里k ~ (1 ~ 10),所以开一个辅助数组t[11] [11],t [ i ] [ j ]表示i % k == a % k == j,即满足(i - a) % k == 0,那么就可以直接对编好号的线段树进行操作就可以了。

#include <map>#include <set>#include <queue>#include <stack>#include <vector>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#define pi acos(-1.0)#define eps 1e-8#define asd puts("sdasdasdasdasd");typedef long long ll;const int inf = 0x3f3f3f3f;const int N = 50050;struct node{    int l, r, add[55], lazy, x;}tr[N << 2];int t[11][11];    // t[i][j]表示 i % k == a % k == j,即满足(i - a) % k == 0//k = 1时第一个元素为0, k = 2时, 第2,3个元素为0, 1....依次类推int n, q;void build( int l, int r, int rt ){    tr[rt].l = l;    tr[rt].r = r;    memset( tr[rt].add, 0, sizeof( tr[rt].add ) );    tr[rt].lazy = 0;    if( l == r )    {        scanf("%d", &tr[rt].x);        return;    }    int mid = (l + r) >> 1;    build( lson );    build( rson );}void down( int rt ){    if( tr[rt].lazy )    {        tr[rt<<1].lazy += tr[rt].lazy;        tr[rt<<1|1].lazy += tr[rt].lazy;        tr[rt].lazy = 0;        for( int i = 0; i < 55; i++ )        {            tr[rt<<1].add[i] += tr[rt].add[i];            tr[rt<<1|1].add[i] += tr[rt].add[i];            tr[rt].add[i] = 0;        }    }}void update( int l, int r, int rt, int k, int mod, int x ){    if( l <= tr[rt].l && tr[rt].r <= r )    {        tr[rt].lazy += x;        tr[rt].add[ t[k][mod] ] += x;        return;    }    down( rt );    int mid = ( tr[rt].l + tr[rt].r ) >> 1;    if( l <= mid )        update( l, r, rt << 1, k, mod, x );    if( r > mid )        update( l, r, rt << 1 | 1, k, mod, x );}int query( int pos, int rt ){    if( tr[rt].l == tr[rt].r )    {        int res = tr[rt].x;        for( int i = 1; i <= 10; i++ )            res += tr[rt].add[ t[i][pos%i] ];        return res;    }    down( rt );    int mid = ( tr[rt].l + tr[rt].r ) >> 1;    if( pos <= mid )        return query( pos, rt << 1 );    else        return query( pos, rt << 1 | 1 );}int main(){    int cnt = 0;    for( int i = 1; i <= 10; ++i )    {        for( int j = 0; j < i; ++j )            t[i][j] = cnt++;    }    while( ~scanf("%d", &n) )    {        build( 1, n, 1 );        scanf("%d", &q);        int a, b, c, k, op;        while( q-- )        {            scanf("%d", &op);            if( op == 1 )            {                scanf("%d%d%d%d", &a, &b, &k, &c);                update( a, b, 1, k, a % k, c );            }            else            {                scanf("%d", &a);                int ans = query( a, 1 );                printf("%d\n", ans);            }        }    }    return 0;}


0 0
原创粉丝点击