HDU 5057 Argestes and Sequence --树状数组(卡内存)

题意:给n个数字,每次两种操作: 1.修改第x个数字为y。 2.查询[L,R]区间内第D位为P的数有多少个。

解法:这题当时被卡内存了,后来看了下别人代码发现可以用unsigned short神奇卡过,于是学习了。

这种区间求和的问题很容易想到树状数组,根据第i位为j(i<10,j<10)建立100棵树状数组(由于内存100*100000被卡,且看到个数,即c[10][10][100000]的值最多为100000,那么最多分两个unsigned short (0~65535),记录一下就可以了)。 然后两种操作都非常常规,就不讲了。

限时2500ms,结果跑了2250MS,限内存32768K,结果内存30008K,纯粹是卡过去的。

好像正解是离线算法或者分块,但是不会写,以后会写了再更新吧。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

using namespace std;

#define N 100003



unsigned short c[10][10][N];

bool f[10][10][N];

int n,m;

int a[N];

int ten[11] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};



int lowbit(int x) { return x&-x; }



void modify(int D,int P,int x,int val)

{

    while(x <= n)

    {

        c[D][P][x] += val;

        if(c[D][P][x] > 50000) c[D][P][x] -= 50000, f[D][P][x] = 1;

        x += lowbit(x);

    }

}



int getsum(int D,int P,int x)

{

    int res = 0;

    while(x > 0)

    {

        res += c[D][P][x];

        if(f[D][P][x]) res += 50000;

        x -= lowbit(x);

    }

    return res;

}



int main()

{

    int i,j,t;

    char ss[4];

    int x,y,L,R,D,P;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d",&n,&m);

        memset(c,0,sizeof(c));

        memset(f,0,sizeof(f));

        for(i=1;i<=n;i++)

        {

            scanf("%d",&a[i]);

            for(j=0;j<10;j++)

            {

                int num = a[i]/ten[j];

                num %= 10;

                modify(j,num,i,1);

            }

        }

        while(m--)

        {

            scanf("%s",ss);

            if(ss[0] == 'Q')

            {

                scanf("%d%d%d%d",&L,&R,&D,&P);

                D--;

                printf("%d\n",getsum(D,P,R) - getsum(D,P,L-1));

            }

            else

            {

                scanf("%d%d",&x,&y);

                for(i=0;i<10;i++)

                {

                    int num = a[x]/ten[i];

                    num %= 10;

                    modify(i,num,x,-1);

                }

                for(i=0;i<10;i++)

                {

                    int num = y/ten[i];

                    num %= 10;

                    modify(i,num,x,1);

                }

                a[x] = y;

            }

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(sequence)