HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。
第一行:一个整数N,表示项链的长度。
第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。
第三行:一个整数M,表示HH 询问的个数。
接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
M 行,每行一个整数,依次表示询问对应的答案。
输入输出样例
输入样例#1:
6
1 2 3 4 3 5
3
1 2
3 5
2 6
输出样例#1:
2
2
4
对于100%的数据,N <= 50000,M <= 200000。
终于不是线段树裸题了,尽管还是有些水(对于大牛来说),但我了翘了3节自习才调出来(我还是太弱)
听说有神犇用莫队做,但我这种蒟蒻就只好用线段树了
大概思路是这样:
首先把数据预处理好,具体是看每一个是不是在前面有同类的,如果有就算一种。
然后在把每次查询以区间左端点从小到大排序(为什么能排序呢,因为没有修改操作),之后我们发现,如果下一个区间的左端点比上一个区间大的话,就需要更新了。当然不必担心更新的时间复杂度,我们只需要把在两个区间左端点之间的点全部舍去,再把同一种类的next点算上一种就可以了,复杂度O(logn)。然后后,你会惊讶的发现这就是—-区间求和!(蛤蛤)
代码如下(首先给大家看一下自己的wa记录)
/**************************************************************
Problem: 1878
User: infinityedge
Language: C++
Result: Accepted
Time:2572 ms
Memory:13400 kb
****************************************************************/
#include
#include
#include
#include
using namespace std;
struct node {
int l1,r1,bh;
} a[200005];
int dt[200005];
int n,m,itmp[50005],ans[200005];
int nxt[1000005],pre[1000005],b[50005];
void init(int k,int l,int r) {
if (r-l==1) {
dt[k]=b[l];
return;
}
int chl=k*2,chr=k*2+1;
init(chl,l,(l+r)/2);
init(chr,(l+r)/2,r);
dt[k]=dt[chl]+dt[chr];
}
void updd(int a,int k,int l,int r) {
if(a=r)return;
if (l==a&&r-l==1) {
b[a]=1;
dt[k]=b[a];
return;
}
int chl=k*2,chr=k*2+1;
updd(a,chl,l,(l+r)/2);
updd(a,chr,(l+r)/2,r);
dt[k]=dt[chl]+dt[chr];
}
int query(int a,int b,int k,int l,int r) {
if(b<=l||a>=r)return 0;
if(a<=l&&b>=r) {
return dt[k];
}
if(r-l!=1) {
int chl=k*2,chr=k*2+1;
int res=query(a,b,chl,l,(l+r)/2)+query(a,b,chr,(l+r)/2,r);
return res;
}
}
int cmp(node a,node b) {
if (a.l1==b.l1) return a.r1else return a.l1int main() {
memset(dt,0,sizeof(dt));
memset(itmp,0,sizeof(itmp));
memset(nxt,0,sizeof(nxt));
memset(pre,0,sizeof(pre));
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&itmp[i]);
}
for(int i=1; i<=n; i++) {
nxt[pre[itmp[i]]]=i;
if(!pre[itmp[i]])b[i]=1;
pre[itmp[i]]=i;
}
init(1,1,n+1);
scanf("%d",&m);
for(int i=1; i<=m; i++) {
scanf("%d%d",&a[i].l1,&a[i].r1);
a[i].bh=i;
}
sort(a+1,a+m+1,cmp);
for (int i=1; i<=m; i++) {
if (a[i-1].l1!=a[i].l1)
for (int j=a[i-1].l1; j<=a[i].l1-1; j++)
if (nxt[j])updd(nxt[j],1,1,n+1);
ans[a[i].bh]=query(a[i].l1,a[i].r1+1,1,1,n+1);
}
for(int i=1;i<=m;i++){
printf("%d\n",ans[i]);
}
return 0;
}