Problem C
发布时间: 2017年6月28日 11:38 最后更新: 2017年6月28日 16:38 时间限制: 1000ms 内存限制: 32M
给定一个长度为 n 的序列 a1 , a2 , ..., an , 其中 ai∈[1,10]
给出 q 个操作, 操作分为两种
对于形如 1 x y 的操作, 将 ax 改为 y , 满足 1≤x≤n , 1≤y≤10
对于形如 2 x y z 的操作, 输出下标介于 [x,y] 之间的元素中, 值为 z 的元素个数, 满足 1≤x≤y≤n , 1≤z≤10
9×104≤n≤105 , 9×104≤q≤105
第一行两个整数
n
,
q
, 意义如上所述。
接下来
q
行, 每行第一个数为
opt
, 如果
opt=1
, 后面紧跟两个数, 意义如上所述; 如果
opt=2
, 后面紧跟三个数, 意义如上所述。
对于每个操作 3 , 输出答案, 一行一个。
8 3 3 1 4 1 5 9 2 6 2 1 8 2 1 2 2 2 1 8 2
1 2
非常简单的一道题目,开10个树状数组。
bitree[z]含义分别是值为z的位置分布的树状数组。
当把数字a[x]变成y的时候,要做两件事情
第一件:消除旧值的影响
add(a[x],x,-1);
第二件
a[x] = y
add(a[x],x,1)
增加对新的数的影响
查询区间[x,y]等于z的数的个数时候
直接在z对应的树状数组里求部分和就OK了
是不是非常简单
#include <cstdio>
const int MAX = 1e5+7;
int a[MAX];
int in[11][MAX];
int n,q;
inline int lowbit(int x){
return x&(-x);
}
void add(int id,int pos,int val){
while(pos <= n){
in[id][pos] += val;
pos += lowbit(pos);
}
}
int getsum(int id,int pos){
int res = 0;
while(pos){
res += in[id][pos];
pos -= lowbit(pos);
}
return res;
}
int main(){
scanf("%d%d",&n,&q);
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
add(a[i],i,1);
}
while(q--){
int opt;scanf("%d",&opt);
if(opt == 1){
int x,y;
scanf("%d%d",&x,&y);
add(a[x],x,-1);
a[x] = y;
add(a[x],x,1);
}
else {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",getsum(z,y) - getsum(z,x-1));
}
}
}