zoukankan      html  css  js  c++  java
  • 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
    ",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
  • 相关阅读:
    JDK11 | 第七篇 : ZGC 垃圾收集器
    JDK11 | 第六篇 : Epsilon 垃圾收集器
    JDK11 | 第五篇 : 启动单个Java源代码文件的程序
    JDK11 | 第四篇 : 增强API
    JDK11 | 第三篇 : 局部变量类型推断
    JDK11 | 第二篇 : JShell 工具
    JDK11 | 第一篇 : JDK11 介绍
    客户端负载均衡Ribbon之源码解析
    DockerSwarm 微服务部署
    DockerSwarm 集群环境搭建
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4000067.html
Copyright © 2011-2022 走看看