bzoj 1878(离线+树状数组)

来源:互联网 发布:北京天文馆网络售票 编辑:程序博客网 时间:2024/05/16 08:21

1878: [SDOI2009]HH的项链

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 2696  Solved: 1353
[Submit][Status][Discuss]

Description

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。

Input

第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

Output

M行,每行一个整数,依次表示询问对应的答案。

Sample Input

6
1 2 3 4 3 5
3
1 2
3 5
2 6

Sample Output

2
2
4

HINT


对于20%的数据,N ≤ 100,M ≤ 1000;
对于40%的数据,N ≤ 3000,M ≤ 200000;

对于100%的数据,N ≤ 50000,M ≤ 200000。


解题思路:首先想到线段树,但是空间太小,想来想去,只能离线,然后树状数组,

记入下每个数在序列中对应的所有位置。

对讯问按照起点排序。用tail来当做原数组的指针。如果tail<start[i]就要剪掉之间

所有数,在维护后一个同样数所在的位置(树状数组)。



#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,ans,q,len;
int a[51000],messi[51000];
struct ss
 {
  int x,y,dui;
 }g[210000];
 int zhong[1100001],to[51000],h[1100001],next[51000];
 int sum[210000];


inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return f*x;
}


bool cmp(ss xg,ss yg)
 {
  return xg.x<yg.x;
 }


void add(int now,int zhi)
 {
  while (now<=n) 
     {
      messi[now]+=zhi;
      now+=now&-now;
}
 }


int query(int o)
{
int sum=0;
while (o>0)
{
sum+=messi[o];
o-=o&-o;
}
return sum;
}


void insert(int x,int y)
 {
  ++len;
  to[len]=y; next[len]=h[x]; h[x]=len;
 }


int main()
{
n=read();
for (int i=1;i<=n;++i)
{
 a[i]=read();
 if (zhong[a[i]]==0)
  {
  add(i,1);
  }
 ++zhong[a[i]];
}
for (int i=n;i>=1;--i)
     {
      insert(a[i],i);
}
q=read();
for (int i=1;i<=q;++i)
{
g[i].x=read(); g[i].y=read(); g[i].dui=i;
}
sort(g+1,g+q+1,cmp);
int tail=1;
    for (int i=1;i<=q;++i)
     {
        while (tail<g[i].x)
      {
      add(tail,-1);
      h[a[tail]]=next[h[a[tail]]];
      if (h[a[tail]]!=0)
      {
      add(to[h[a[tail]]],1);
}
      ++tail;
}
sum[g[i].dui]=query(g[i].y)-query(g[i].x-1);
}
for (int i=1;i<=q;++i)
{
printf("%d\n",sum[i]);
}
}

0 0
原创粉丝点击