hdu 5057 Argestes and Sequence(树状数组)

本文探讨了如何利用离线处理和树状数组解决内存管理问题,特别关注于如何通过离线处理减少内存占用,并使用树状数组进行区间求和操作以优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hdu 5057 Argestes and Sequence

主要的考点是对内存的把控。由于各个十进制位上的数互不影响,所以可以将询问保存再离线处理。区间求和明显需要用到树状数组。

#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <set>
#include <iostream>
#include <cmath>
using namespace std;
#ifdef __GNUC__
typedef long long LL;
inline void opt64(LL a) {
    printf("%lld", a);
}
#else
typedef __int64 LL;
inline void opt64(LL a) {
    printf("%I64d", a);
}
#endif
const int MAXN = 100002;
int n, m, x, y;
int ac[MAXN], cur, ab[MAXN];
struct query
{
    int L, R, P, d, r;
} kp;
vector<query> mmp[11];
int sdd[MAXN][3];
int ten[11];
struct node
{
    int dp[10];
    void init() {
        memset(dp, 0, sizeof dp);
    }
    void cal(int a)
    {
        init();
        a /= ten[cur-1];
        ++dp[a%10];
    }
    node operator - (const node & a)
    {
        node res;
        res.init();
        for (int j = 0; j< 10; ++j)
        {
            res.dp[j] = dp[j] - a.dp[j];
        }
        return res;
    }
    node operator + (const node & a)
    {
        node res;
        res.init();
        for (int j = 0; j< 10; ++j)
        {
            res.dp[j] = dp[j] + a.dp[j];
        }
        return res;
    }
} da[MAXN], db, dc;
int low_bit(int x)
{
    return x&(-x);
}
void change(int x, node a)
{
    while (x <= n)
    {
        da[x] = da[x] + a;
        x += low_bit(x);
    }
}
int get_sum(int x, int p)
{
    int res = 0;
    while (x > 0)
    {
        res += da[x].dp[p];
        x -= low_bit(x);
    }
    return res;
}
char ss[5];
int rres[MAXN], nr;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int t, a, cnt;
    ten[0] = 1;
    for (int i = 1; i< 10; ++i) ten[i] = ten[i-1]*10;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d", &n, &m);
        cnt = nr = 0;
        for (int i = 1; i<= n; ++i) scanf("%d", ac+i);
        for (int i = 0; i< 11; ++i) mmp[i].clear();
        for (int i = 1; i<= m; ++i)
        {
            scanf("%s", ss);
            if (ss[0] == 'Q')
            {
                int o;
                scanf("%d%d%d%d", &kp.L, &kp.R, &o, &kp.P);
                kp.d = i;
                kp.r = nr++;
                mmp[o].push_back(kp);
            }
            else
            {
                sdd[++cnt][0] = i;
                scanf("%d%d", &sdd[cnt][1], &sdd[cnt][2]);
            }
        }
        for (int i = 1, k; i< 11; ++i)
        {
            cur = i;
            if ((k=mmp[i].size()) == 0) continue;
            for (int j =0; j<= n; ++j) da[j].init();
            memcpy(ab, ac, sizeof ac);
            for (int j =1; j<= n; ++j)
                db.cal(ab[j]), change(j, db);
            int bg = 1;
            for (int j = 0; j< k; ++j)
            {
                query sp = mmp[i][j];
                while (bg<=cnt && sdd[bg][0] < sp.d)
                {
                    db.cal(sdd[bg][2]);
                    dc.cal(ab[sdd[bg][1]]);
                    change(sdd[bg][1], db-dc);
                    ab[sdd[bg][1]] = sdd[bg][2];
                    ++bg;
                }
                rres[sp.r] = get_sum(sp.R, sp.P) - get_sum(sp.L-1, sp.P);
            }
        }
        for (int i = 0; i< nr; ++i) printf("%d\n", rres[i]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值