AtCoder Beginner Contest 174 比赛人数9817
AtCoder Beginner Contest 174 F Range Set Query 离线处理+连续区间自左向右处理+树状数组定位颜色位置(一种颜色只记录一次,绝不重复)
总目录详见https://blog.csdn.net/mrcrack/article/details/104454762
在线测评地址https://atcoder.jp/contests/abc174/tasks/abc174_f
题目大意:给定一行有颜色的球,有Q次询问,问区间[l,r]包含的球的颜色的数量。
基本思路:离线处理+连续区间自左向右处理+树状数组定位颜色位置(一种颜色只记录一次,绝不重复)
#include <cstdio>
#include <algorithm>
#define maxn 500010
using namespace std;
int n,m;
int c[maxn],book[maxn],tree[maxn],ans[maxn];
struct node{
int l,r,seq;
}q[maxn];
int lowbit(int x){
return x&-x;
}
void add(int pos,int val){
while(pos<=n){
tree[pos]+=val;
pos+=lowbit(pos);
}
}
int sum(int pos){
int ret=0;
while(pos>0){
ret+=tree[pos];
pos-=lowbit(pos);
}
return ret;
}
int cmp(node a,node b){
return a.r<b.r;
}
int main(){
int i,j,start;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&c[i]);
for(i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].seq=i;
sort(q+1,q+1+m,cmp);//按右边界自小到大排序
start=1;
for(i=1;i<=m;i++){
for(j=start;j<=q[i].r;j++){//神奇,以r为边界,进行处理。
if(book[c[j]])add(book[c[j]],-1);//删除之前的颜色,只保留一个颜色
add(j,1),book[c[j]]=j;//标记该颜色现在位置
}
start=q[i].r+1;//连续区间处理
ans[q[i].seq]=sum(q[i].r)-sum(q[i].l-1);
}
for(i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}