您的位置:首页 > 其它

主席树|线段树(区间不同的数的个数)spoj3267

2014-09-18 13:22 471 查看

3267. D-query

Problem code: DQUERY

English
Vietnamese

Given a sequence of n numbers a1, a2, ..., an 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 ai, ai+1, ..., aj.

Input

Line 1: n (1 ≤ n ≤ 30000).
Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).

Output

For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.

Example

Input
5
1 1 2 1 3
3
1 5
2 4
3 5

Output
3
2
3


首先是线段树解法,跟hdu上的几个题是一样的

#include<stdio.h>  
#include<algorithm>  
#include<string.h>  
#include<map>  
#define N 35000  
#define M 250000  
using namespace std;  
struct node  
{  
  int x,y,id;  
}b[M];  
int c
,ans[M],a
;  
map<int ,int >ma;  
bool cmp(node a,node b)  
{  
  return a.y<b.y;  
}  
int lowbit(int x)  
{  
  return x&(-x);  
}  
void update(int x,int val)  
{  
   while(x<=N)  
   {  
     c[x]+=val;  
     x+=lowbit(x);  
   }  
}  
int sum(int x)  
{  
  int s=0;  
  while(x)  
  {  
   s+=c[x];  
   x-=lowbit(x);  
  }  
  return s;  
}  
int main()  
{  
   int n,i,m,pre,j;  
   //freopen("a.txt","r",stdin);  
   while(scanf("%d",&n)!=EOF)  
   {  
     for(i=1;i<=n;i++)  
       scanf("%d",&a[i]);  
      scanf("%d",&m);  
      for(i=0;i<m;i++)  
      {  
        scanf("%d%d",&b[i].x,&b[i].y);  
        b[i].id=i;  
      }  
      sort(b,b+m,cmp);  pre=1;  
      memset(c,0,sizeof(c));  
      for(i=0;i<m;i++)  
      {  
        for(j=pre;j<=b[i].y;j++)  
        {  
           if(ma.find(a[j])==ma.end())  
                update(j,1);  
            else  
            {  
               update(ma[a[j]],-1);  
               update(j,1);  
            }  
            ma[a[j]]=j;  
        }  
        ans[b[i].id]=sum(b[i].y)-sum(b[i].x-1);  
        pre=b[i].y+1;  
      }  
      for(i=0;i<m;i++)  
        printf("%d\n",ans[i]);  
   }  
   return 0;  
}


然后是主席树,主席树保存前缀1...i出现在1...n的数有多少

查询的时候对于(l,r),之需要查询T[r]这个数,1...l有多少个不同的数,然后用总数减掉就可以了

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=30010;
const int maxm=maxn*100;
int n,q,m,num;
int a[maxn];
int cnt[maxm],lson[maxm],rson[maxm];
int T[maxm];
map<int,int> vis;
int build(int l,int r)
{
    int root=num++;
    cnt[root]=0;
    if(l!=r)
    {
        int mid=(l+r)>>1;
        lson[root]=build(l,mid);
        rson[root]=build(mid+1,r);
    }
    return root;
}
int update(int root,int pos,int val)
{
    int newroot=num++,tmp=newroot;
    int l=1,r=n;
    cnt[newroot]=cnt[root]+val;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(pos<=mid)
        {
            r=mid;
            lson[newroot]=num++,rson[newroot]=rson[root];
            newroot=lson[newroot],root=lson[root];
        }
        else
        {
            l=mid+1;
            rson[newroot]=num++;lson[newroot]=lson[root];
            newroot=rson[newroot],root=rson[root];
        }
        cnt[newroot]=cnt[root]+val;
    }
    return tmp;
}
int query(int root,int pos)
{
    int l=1,r=n,ans=0;
    while(pos>l)
    {
        int mid=(l+r)>>1;
        if(pos<=mid)
        {
            r=mid;
            root=lson[root];
        }
        else
        {
            l=mid+1;
            ans+=cnt[lson[root]];
            root=rson[root];
        }
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        scanf("%d",&q);
        num=0;
        vis.clear();
        T[0]=build(1,n);
        for(int i=1;i<=n;i++)
        {
            if(vis.count(a[i]))
            {
                int tmp=update(T[i-1],vis[a[i]],-1);
                T[i]=update(tmp,i,1);
            }
            else
            {
                T[i]=update(T[i-1],i,1);
            }
            vis[a[i]]=i;
        }
        while(q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",cnt[T[r]]-query(T[r],l));
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: