hdu 5057 Argestes and Sequence (数状数组+离线处理)

题意:

给N个数。a[1]....a[N]。

M种操作:

S X Y:令a[X]=Y

Q L R D P:查询a[L]...a[R]中满足第D位上数字为P的数的个数

数据范围:

1<=T<= 50
1<=N, M<=100000
0<=a[i]<=$2^{31}$ - 1
1<=X<=N
0<=Y<=$2^{31}$ - 1
1<=L<=R<=N
1<=D<=10
0<=P<=9

思路:

直接开tree[maxn][10][10]记录第i位上数字为j的个数,铁定MLE,采用离线省去一维。

枚举位置(第i位),每一次枚举,扫一下M个操作,记录。

额.. 直接看代码

代码:

#include <cstdio>
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <stack>
using namespace std;
int const uu[4] = {1,-1,0,0};
int const vv[4] = {0,0,1,-1};
typedef long long ll;
int const inf = 0x3f3f3f3f;
ll const INF = 0x7fffffffffffffffll;
double eps = 1e-10;
double pi = acos(-1.0);
#define rep(i,s,n) for(int i=(s);i<=(n);++i)
#define rep2(i,s,n) for(int i=(s);i>=(n);--i)
#define mem(v,n) memset(v,(n),sizeof(v))
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(x) (x)&(-(x))
struct node1{
    int kind, L, R, D, P, pos, value; //kind=0,Q操作  kind=1,S操作
}O[100005];

int const maxn=100005;
int T,n,m;
int a[maxn], aa[maxn];
int C[maxn][10]; //第二维:位上的数字
int ans[maxn];

void update(int kind,int p,int x){ //x:位上的数字
    for(int i=p;i<=n;i+=lowbit(i)){
        if(kind==0)
            ++C[i][x];
        else
            --C[i][x];
    }
}

int sum(int p,int P){
    int ret=0;
    for(int i=p;i>0;i-=lowbit(i))
        ret+=C[i][P];
    return ret;
}

int query(int L,int R,int P){
    return sum(R,P)-sum(L-1,P);
}

int POW(int base,int k){
    int ret=1;
    while(k--) ret*=10;
    return ret;
}

int main(){
    cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);

        rep(i,1,n){
            scanf("%d",&a[i]);
            aa[i]=a[i];
        }

        char op[10];
        rep(kk,1,m){
            scanf("%s",op);
            int x,y,L,R,D,P;
            if(op[0]==‘S‘){
                scanf("%d%d",&x,&y);
                O[kk].kind=1, O[kk].pos=x, O[kk].value=y;
            }else{
                scanf("%d%d%d%d",&L,&R,&D,&P);
                O[kk].kind=0, O[kk].L=L, O[kk].R=R, O[kk].D=D, O[kk].P=P;
            }
        }

        rep(i,1,10){// 第i位
            mem(C,0);
            rep(j,1,n){
                a[j]=aa[j];
                int t1=a[j]/POW(10,i-1)%10; //第i位上的数字
                update(0,j,t1);
            }
            rep(j,1,m){
                if(O[j].kind==1){ //更改操作
                    int t1=a[O[j].pos]/POW(10,i-1)%10;
                        update(1, O[j].pos, t1);
                    int t2=O[j].value/POW(10,i-1)%10;
                        update(0, O[j].pos, t2);
                        a[O[j].pos]=O[j].value;
                }else{
                    if(O[j].D==i){ //查询操作
                        ans[j]=query(O[j].L,O[j].R,O[j].P);
                    }
                }
            }
        }
        rep(i,1,m) if(O[i].kind==0) printf("%d\n",ans[i]);
    }
    return 0;
}
时间: 2024-11-03 21:44:08

hdu 5057 Argestes and Sequence (数状数组+离线处理)的相关文章

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),记录一下就可以了

Necklace HDU - 3874 (线段树/树状数组 + 离线处理)

Necklace HDU - 3874 Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count

HDU 3333 Turing Tree(树状数组离线处理)

HDU 3333 Turing Tree 题目链接 题意:给定一个数组,每次询问一个区间,求出这个区间不同数字的和 思路:树状数组离线处理,把询问按右端点判序,然后用一个map记录下每个数字最右出现的位置,因为一个数字在最右边出现,左边那些数字等于没用了,利用树状数组进行单点修改区间查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <map> using n

hdu 5057 Argestes and Sequence

Argestes and Sequence Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 511    Accepted Submission(s): 127 Problem Description Argestes has a lot of hobbies and likes solving query problems espec

hdu 5057 Argestes and Sequence(分块算法)

Argestes and Sequence Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 566    Accepted Submission(s): 142 Problem Description Argestes has a lot of hobbies and likes solving query problems espec

hdu 3333 树状数组+离线处理

http://acm.hdu.edu.cn/showproblem.php?pid=3333 不错的题,想了很久不知道怎么处理,而且答案没看懂,然后找个例子模拟下别人的代码马上懂了---以后看不懂的话就拿个例子模拟下别人的代码 举个例子:1 3 3 5 3 5 查询 a, 2 4 b, 2 5 最初是这么想的:对于a查询,倘若把第二个数第三个数变成1个3,那么到b查询,又出现了两个3,再做处理似乎还是O(n),而且如果先出现2,5查询,后出现2,4查询,那么还需要把删除的数补回来.....o(╯

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

HDU 4417 Super Mario ( 超级马里奥 + 主席树 + 线段树/树状数组离线处理 + 划分树 )

HDU 4417 - Super Mario ( 主席树 + 线段树/树状数组离线处理 + 划分树 ) 这道题有很多种做法,我先学习的是主席树.后面陆续补上线段树离线和划分树 题目大意就是给定一个区间给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 主席树做法: 最基本的是静态第k大,这里是求静态的 <= K,差不多,在Query操作里面需要修改修改 先建立size棵主席树,然后询问的时候统计的是 第R棵主席树中[1,K]的数量 - 第L-1棵主席树中[1,K]的数量 注意这里下标

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的