→题目链接←
这个题我傻逼了
看到区间查询我下意识地打了线段树
然后一发A了后发现其他人的代码都好快啊
找题解发现都是用的前缀和
靠!
然后又搞了一发前缀和
我把两个代码都放上来吧
前缀和:
#include<iostream>
#include<cstdio>
using namespace std;
int n,m;
int sum1[100010],sum2[100010],sum3[100010];
int main(){
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++){
int x;
scanf("%d",&x);
if(x==1)sum1[i]=1;
if(x==2)sum2[i]=1;
if(x==3)sum3[i]=1;
sum1[i]+=sum1[i-1];
sum2[i]+=sum2[i-1];
sum3[i]+=sum3[i-1];
}
while(m--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d %d %d\n",sum1[y]-sum1[x-1],sum2[y]-sum2[x-1],sum3[y]-sum3[x-1]);
}
return 0;
}
线段树:
#include<iostream>
#include<cstdio>
using namespace std;
struct node{
int l,r;
int num1,num2,num3;
}tree[400040];
int n,m;
int ans1,ans2,ans3;
void build(int x,int l,int r){
tree[x].l=l;
tree[x].r=r;
if(l==r){
int y;
scanf("%d",&y);
if(y==1)tree[x].num1=1;
else if(y==2)tree[x].num2=1;
else tree[x].num3=1;
return;
}
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
tree[x].num1=tree[x*2].num1+tree[x*2+1].num1;
tree[x].num2=tree[x*2].num2+tree[x*2+1].num2;
tree[x].num3=tree[x*2].num3+tree[x*2+1].num3;
return;
}
void chaxun(int x,int l,int r){
if(tree[x].r<l || tree[x].l>r)return;
if(tree[x].l>=l && tree[x].r<=r){
ans1+=tree[x].num1;
ans2+=tree[x].num2;
ans3+=tree[x].num3;
return;
}
int mid=(tree[x].l+tree[x].r)/2;
if(mid<l)chaxun(x*2+1,l,r);
else if(mid>=r)chaxun(x*2,l,r);
else chaxun(x*2,l,r),chaxun(x*2+1,l,r);
return;
}
int main(){
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
ans1=ans2=ans3=0;
chaxun(1,x,y);
printf("%d %d %d\n",ans1,ans2,ans3);
}
return 0;
}