HDU_5057_分块

http://acm.hdu.edu.cn/showproblem.php?pid=5057

分块,保存每个块中每位对应数字的和,复杂的是getmum,左右下标所在的块不能直接读取block数组,要重新自己计算。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

int a[100005],belong[100005],L[100005],R[100005],block[400][11][10],n,m;
int ten[11] = {0,1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};

void build()
{
    int sizee = sqrt(n);
    int num = n/sizee;
    if(n%sizee)  num++;
    for(int i = 1;i <= num;i++)
    {
        L[i] = (i-1)*sizee+1;
        R[i] = i*sizee;
    }
    for(int i = 1;i <= n;i++)   belong[i] = (i-1)/sizee+1;
    for(int i = 1;i <= n;i++)
    {
        int temp = a[i];
        for(int j = 1;j <= 10;j++)
        {
            block[belong[i]][j][temp%10]++;
            temp /= 10;
        }
    }
}

int getnum(int l,int r,int d,int p)
{
    int ans = 0;
    if(belong[l] == belong[r])
    {
        for(int i = l;i <= r;i++)
        {
            if((a[i]/ten[d])%10 == p) ans++;
        }
        return ans;
    }

    for(int i = belong[l]+1;i < belong[r];i++)  ans += block[i][d][p];
    for(int i = l;i <= R[belong[l]];i++)
    {
        if((a[i]/ten[d])%10 == p) ans++;
    }
    for(int i = L[belong[r]];i <= r;i++)
    {
        if((a[i]/ten[d])%10 == p) ans++;
    }
    return ans;
}

void update(int x,int y)
{
    for(int i = 1;i <= 10;i++)
    {
        block[belong[x]][i][a[x]%10]--;
        a[x] /= 10;
    }
    a[x] = y;
    for(int i = 1;i <= 10;i++)
    {
        block[belong[x]][i][y%10]++;
        y /= 10;
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(block,0,sizeof(block));
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
        build();
        char s[5];
        while(m--)
        {
            scanf("%s",s);
            if(s[0] == ‘S‘)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                update(x,y);
            }
            else
            {
                int l,r,d,p;
                scanf("%d%d%d%d",&l,&r,&d,&p);
                printf("%d\n",getnum(l,r,d,p));
            }
        }
    }
    return 0;
}
时间: 2024-10-10 08:06:19

HDU_5057_分块的相关文章

CodeChef FNCS (分块+树状数组)

题目:https://www.codechef.com/problems/FNCS 题解: 我们知道要求区间和的时候,我们用前缀和去优化.这里也是一样,我们要求第 l 个函数到第 r 个函数 [l, r] 的函数和,那么我们可以用 sum[r] - sum[l-1] 来求得. 由于这个数据量有点大,所以我们将函数分块. 例如样例: 1 3 有5个函数,那么我们分成3块.{ [1 3] , [2 5] }, { [4 5], [3 5] }, { [1 2] }.每一块对应都有一个sum ,这时如

分块算法及模板

此文为博主原创,转载时请通知博主,并把原文链接放在正文醒目位置. 简要介绍 分块算法就是把一串数据分割成几块数据的算法,其实是对暴力的一种优化. 通常在分块时,每块的大小为√n.但最后一块的大小也可能小于√n,只能用暴力来算. 通过把对单个数据的操作转化为对几个块的数据的操作,能够节省时间,提高运算效率. 分块算法在处理大范围的修改.查询问题时有很大优势. 分块算法代码 1 /*此代码主要模仿了钟皓曦大佬的分块算法*/ 2 #include<iostream> 3 #include<cs

A - 敌兵布阵(分块)

C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视. 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:"Tidy,马上汇

gcd的性质+分块 Bzoj 4028

4028: [HEOI2015]公约数数列 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 865  Solved: 311[Submit][Status][Discuss] Description 设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作: 1. MODIFY id x: 将 a_{id} 修改为 x. 2. QUERY x: 求最小的整数 p (0 <= p < n),使

主席树 或者 离散化+分块 BZOJ 4636

4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 381  Solved: 177[Submit][Status][Discuss] Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知 道N次操作后数列中所有元素的和.他还要玩其他游戏,所以这个问题留给你解决. Input 第一

bzoj2301 [HAOI2011]Problem b【莫比乌斯反演 分块】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 很好的一道题.首先把每个询问转化为4个子询问,最后的结果就是这四个子询问的记过加加减减,类似二维前缀和.那么问题转化为在1 <= x <= lmtx, 1 <= y <= lmty时gcd(x, y) == k的对数,这个问题在转化一下,转化成1 <= x <= lmtx / k,1 <= y <= lmty / k时x与y互质的对数.莫比乌斯反

POJ2104 K-th Number [分块做法]

传送:主席树做法http://www.cnblogs.com/candy99/p/6160704.html 做那倒带修改的主席树时就发现分块可以做,然后就试了试 思想和教主的魔法差不多,只不过那个是求>=v的有几个 既然一个数v的名次可以求,我们二分这个数就行了啊 然而...... 首先,你二分到的这个数不一定在区间里出现过 比如 1 2 5 8 9 4和5的名次都是3 于是,我修改了某个区间名次的定义: “如果一个数的名次是x,但是区间中没有次数,那么他的名次为x-1” 实现上只需要find里

asp.net core分块上传文件

写完asp.net多文件上传(http://www.cnblogs.com/bestckk/p/5987383.html)后,感觉这种上传还是有很多缺陷,于是...(省略一万字,不废话).这里我没用传统的asp.net,而选择了开源的asp.net core,原因很简单,.net core是.net新的开始,更是.net和.net开发者的未来,希望.net发展越来越好(大家的工资越来越高(●ˇ?ˇ●)). 1.前端的实现: 1).html: 1 <html> 2 <head> 3

CodeForces 455D 分块

题目链接:http://codeforces.com/problemset/problem/455/D 题意:给定一个长度为n的序列a[]. m次操作.共有两种操作 1 l r:将序列的a[l].a[l+1]...a[r]变成a[r].a[l].a[l+1]...a[r-1]:2 l r k:求序列a[l].a[l+1]...a[r]中有多少个值为k. 输入的l,r,k都是加密过的.所以要解密一下.规则为 l=(l+ans-1)%n+1  r=(r+ans-1)%n+1 k=(k+ans-1)%