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): 583    Accepted Submission(s): 147


Problem Description
Argestes has a lot of hobbies and likes solving query problems especially. One day Argestes came up with such a problem. You are given a sequence a consisting of N nonnegative integers, a[1],a[2],...,a[n].Then there are M operation on the sequence.An operation can be one of the following:
S X Y: you should set the value of a[x] to y(in other words perform an assignment a[x]=y).
Q L R D P: among [L, R], L and R are the index of the sequence, how many numbers that the Dth digit of the numbers is P.
Note: The 1st digit of a number is the least significant digit.
 

Input
In the first line there is an integer T , indicates the number of test cases.
For each case, the first line contains two numbers N and M.The second line contains N integers, separated by space: a[1],a[2],...,a[n]—initial value of array elements.
Each of the next M lines begins with a character type.
If type==S,there will be two integers more in the line: X,Y.
If type==Q,there will be four integers more in the line: L R D P.

[Technical Specification]
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
 

Output
For each operation Q, output a line contains the answer.
 

Sample Input
  
  
1 5 7 10 11 12 13 14 Q 1 5 2 1 Q 1 5 1 0 Q 1 5 1 1 Q 1 5 3 0 Q 1 5 3 1 S 1 100 Q 1 5 3 1
 

Sample Output
  
  
5 1 1 5 0 1
 

——————————————————————分割线——————————————————


题目大意:

给你一个n个数的序列,有两种操作

1:Q L R D P 查询区间[L,R]中第D位为P的数的个数

2:S X Y 替换第X个的元素为Y


思路:

范围为10的5次方

c[k][i][j]表示lowbit(k)区间内第i位为j的数的个数,这样会内存为10的7次方,爆内存,如果用离线操作,就可以减掉一个维度


保存所有的操作,然后进行10次的树状数组就行了


那么这题就是基本的树状数组维护区间和了

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<cmath>

#define forl(i,s,n) for(int i=s;i<n;++i)
#define forle(i,s,n) for(int i=s;i<=n;++i)
#define forg(i,s,n) for(int i=s;i>n;--i)
#define forge(i,s,n) for(int i=s;i>=n;--i)
#define mes(s,c) memset(s,c,sizeof(s))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
template<class T> T Pow(T x,T y){int ret=1;while(y){ret*=x;y--;}return ret;}
template<class T> T lowbit(T x){return x&-x;}
const int maxn=100001;
using namespace std;
int n,m;
int c[maxn][10];
int a[maxn],aa[maxn];
int ans[maxn];
struct operation
{
    int l,r,d,p,x,y;
    int s;
}Op[maxn];
void update(int s,int p,int v)
{
    for(int i=p;i<=n;i+=lowbit(i)){
        if(s==0) c[i][v]++;
        else c[i][v]--;
    }
}
int getsum(int p,int v)
{
    int sum=0;
    for(int i=p;i>0;i-=lowbit(i)){
        sum+=c[i][v];
    }
    return sum;
}
int query(int l,int r,int v)
{
    return getsum(r,v)-getsum(l-1,v);
}

int main()
{
    int T;
    cin>>T;
    while(T--){
        scanf("%d %d",&n,&m);
        forle(i,1,n) {
            scanf("%d",&a[i]);
            aa[i]=a[i];
        }
        forl(i,0,m) {
            char op[2];int l,r,d,p,x,y;
            scanf("%s",op);
            if(op[0]=='Q') {
                scanf("%d %d %d %d",&l,&r,&d,&p);
                Op[i].s=0,Op[i].l=l,Op[i].r=r,Op[i].d=d,Op[i].p=p;//o为查询
            }else {
                scanf("%d %d",&x,&y);
                Op[i].s=1,Op[i].x=x,Op[i].y=y;//1为修改
            }
        }
        forle(i,1,10) {
            mes(c,0);
            forle(j,1,n) {
                aa[j]=a[j];
                int t=a[j]/Pow(10,i-1)%10;
                update(0,j,t);
            }
            forl(j,0,m) {
                if(Op[j].s==1) {
                    int t=aa[Op[j].x]/Pow(10,i-1)%10;
                    update(1,Op[j].x,t);
                    t=Op[j].y/Pow(10,i-1)%10;
                    update(0,Op[j].x,t);
                    aa[Op[j].x]=Op[j].y;
                }else {
                    if(Op[j].d==i){
                        ans[j]=query(Op[j].l,Op[j].r,Op[j].p);
                    }
                }
            }
        }
        forl(i,0,m)
            if(Op[i].s==0) printf("%d\n",ans[i]);

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值