zoukankan      html  css  js  c++  java
  • bzoj1878 [SDOI2009]HH的项链

    1878: [SDOI2009]HH的项链

    Time Limit: 4 Sec  Memory Limit: 64 MB

    Description

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

    Input

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

    Output

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

    Sample Input

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

    Sample Output

    2
    2
    4

    HINT

     

    Source

    Tips:

      这道题你很容易想到用一些线段树,树状数组之类的算法;

      但是却很难用上去;

      因为它是离线的;

      我们可以有序的处理询问,以询问左端点排序;

      现将每个数第一次出现的位置赋值为一,维护一棵线段树,并记录每个数的下一个重复的数的位置;

      当处理到了第i个询问,那么前l[i]个数已经不需要了,将前l[i]个数上的一,转移到next[i]上,做一遍线段树的询问;

    Code:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define MAXN 100008
    using namespace std;
    int n,m,tree[2*MAXN],a[MAXN],next[MAXN],boo[MAXN*10],pre[MAXN];
    int ans[2*MAXN];
    
    struct node{
        int x,y,pos;
    }f[MAXN*2];
    
    int query(int l,int r,int li,int ri,int v){
        if(l==li&&r==ri){
            return tree[v];
        }
        int mid=(l+r) >> 1;
        if(ri<=mid){
            return query(l,mid,li,ri,v<<1);
        }
        if(li>mid){
            return query(mid+1,r,li,ri,(v<<1)+1);
        }
        return query(l,mid,li,mid,v<<1)+query(mid+1,r,mid+1,ri,(v<<1)+1);
    }
    
    void add(int l,int r,int flag,int v){
        if(l==r){
            tree[v]=1;
            return;
        }
        int mid=(l+r) >> 1;
        if(flag<=mid)
            add(l,mid,flag,v<<1);
        else
            add(mid+1,r,flag,(v<<1)+1);
        tree[v]=tree[v<<1]+tree[(v<<1)+1];
    }
    
    bool cmp(node aa,node bb){
        return aa.x<bb.x;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(!boo[a[i]]){
                add(1,n,i,1);
                boo[a[i]]=i;
            }else{
                pre[i]=boo[a[i]];
                boo[a[i]]=i;
                next[pre[i]]=i;
            }
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&f[i].x,&f[i].y);
            f[i].pos=i;
        }
        f[0].x=1;
        sort(f+1,f+m+1,cmp);
        for(int j=1;j<=m;j++){
            for(int i=f[j-1].x;i<f[j].x;i++){
                add(1,n,next[i],1);
            }
            ans[f[j].pos]=query(1,n,f[j].x,f[j].y,1);
        }
        for(int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
    }
  • 相关阅读:
    NABC的特点分析
    梦断代码读后感(三)
    大道至简-“(我) 能不能学会写程序”
    课堂练习-找水王续
    找1
    课堂练习-找水王
    课堂练习-电梯调度
    课堂练习——计算法能够计算出读者购买一批书的最低价格。
    团队项目—二手书店特色
    梦断代码阅读笔记三
  • 原文地址:https://www.cnblogs.com/WQHui/p/7536487.html
Copyright © 2011-2022 走看看