English VietnameseGiven a sequence of n numbers a 1 {1} 1 , a 2 {2} 2 , …, a n {n} n and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence a i {i} i , a i+1 {i+1} i+1 , …, a j {j} j .
题意:给定一串序列,然后m个询问,每个询问求该区间内颜色种类。
算法:离线处理,按照右端点排序,然后从左往右扫一遍
如图所示,我们指针每扫到一个地点就可以吧这种颜色在线段树或者树状数组上的区间修改继续到指针所示的位置,正如蓝色那样,红色和绿色因为之后还没有扫到新的红色和绿色所以没有更新修改,如果有一段区间它的右端点在指针所指的位置,它的左端点如果在S1就会算成3种颜色,因为三种颜色都更新到过了S1,而S2和S3却只有两种和一种,就这样不断地往后推,如果又有新的红色出现的话,红色的标记就会一直更新到红色出现的最后的位置。
下面附上用线段树的代码
/*================================
Author:ylsoi
Problem:SP3267
Time:2018.2.24
================================*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
void File(){
#ifndef ONLINE_JUDGE
freopen("spoj3267.in","r",stdin);
freopen("spoj3267.out","w",stdout);
#endif
}
template<typename T>
void read(T &x){
T _=0;char __=getchar();
while(!isdigit(__))__=getchar();
while(isdigit(__))_=(_<<1)+(_<<3)+(__^'0'),__=getchar();
x=_;
}
template<typename T>
void write(T x){
if(x==0){puts("0\n");return;}
T _=1,__=0;
while(_<=x)_*=10,++__;
while(__--){
_/=10;
putchar(x/_+48);
x%=_;
}
putchar('\n');
}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
const int maxn=3e4+10;
const int maxa=1e6+10;
const int maxm=2e5+10;
struct node{
int l,r,id;
bool operator < (const node &t) const {
return r<t.r;
}
}t[maxm];
int n,m,a[maxn];
#define mid ((l+r)>>1)
#define lson rt*2,l,mid
#define rson rt*2+1,mid+1,r
int sum[maxn<<2],lazy[maxn<<2];
void pushdown(int rt,int l,int r){
sum[rt*2]+=(mid-l+1)*lazy[rt];
sum[rt*2+1]+=(r-mid)*lazy[rt];
lazy[rt*2]+=lazy[rt];
lazy[rt*2+1]+=lazy[rt];
lazy[rt]=0;
}
void update(int rt,int l,int r,int L,int R,int x){
if(L<=l && r<=R){
sum[rt]+=(r-l+1)*x;
lazy[rt]+=x;
return;
}
else{
if(lazy[rt])pushdown(rt,l,r);
if(L<=mid)update(lson,L,R,x);
if(R>=mid+1)update(rson,L,R,x);
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
}
int query(int rt,int l,int r,int L,int R){
if(L<=l && r<=R)return sum[rt];
int ret=0;
if(lazy[rt])pushdown(rt,l,r);
if(L<=mid)ret+=query(lson,L,R);
if(R>=mid+1)ret+=query(rson,L,R);
return ret;
}
int ans[maxm];
vector<int>v[maxa];
void work(){
int k=1;
for(int i=1;i<=n && k<=m;i++){
int c=a[i];
if(v[c].size()==0)v[c].push_back(0);
v[c].push_back(i);
int s=v[c].size()-1;
int pos1=v[c][s-1]+1,pos2=v[c][s];//将c颜色的区间加一从pos1更新到pos2
update(1,1,n,pos1,pos2,1);
while(t[k].r==i){
ans[t[k].id]=query(1,1,n,t[k].l,t[k].l);//直接查询答案就可以
++k;
}
}
}
int main(){
File();
read(n);
REP(i,1,n)read(a[i]);
read(m);
REP(i,1,m){
read(t[i].l);
read(t[i].r);
t[i].id=i;
}
sort(t+1,t+m+1);
work();
REP(i,1,m)write(ans[i]);
return 0;
}