码迷,mamicode.com
首页 > 其他好文 > 详细

HH的项链

时间:2018-10-28 11:14:42      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:cstring   owb   ase   ret   iostream   main   根据   树状数组   div   

分析:

题目描述不说了,大意是,求一段区间内不同元素的种数。

看到区间,我们大概先想到的是暴力(然后炸掉)、线段树、树状数组、分块。

下面给出的是一种树状数组的想法。

首先,对于每一段区间里的数,如果出现重复的元素,我们只需要看最后一个就好了。所以,我们可以对所有需要查询区间的右端点进行从小到大的排序,从左往右枚举右端点维护一个从左向右的树状数组,表示一段区间的种类数。

听不懂的话我们举个栗子例子。

我们假设现在有一个序列:

now为现在的右端点;

insert(i , j)表示在第i 个位置出现了j个位重复的数,就需要我们在我们维护的树状数组序列中+j。

1 ,2 ,1 ,3

now = 1时,insert(1 , 1),树状数组对应的序列就变成了1,0,0,0

now = 2insert(2,1),序列变成了1,1,0,0

now = 3时,我们发现a[3]=1,而1之前已经出现过了,所以最后一次出现的地方(a[1])减1,即insert(1,?1),a[3]这个地方加1,即insert(3,1),序列变成了0,1,1,0

now = 4时,insert(4 , 1),序列变成0,1,1,1

这样的话,我们枚举ii的时候处理一下就OK了.

最后whilewhile输出sum[ ](类似前缀和的一个数组如果查询区间[3~5],就变成sum[5]?sum[2])。

你会发现代码中还有一个last[ ]last[i]根据我的解释应该很好懂吧,表示的就是ii这个元素最后出现的位置。。

好了,代码奉上。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1000005;

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

int n,a[maxn],m;
struct Edge{
    int L,R,val;
}e[maxn << 2];
int last[maxn],sum[maxn],ans[maxn];
int tmp; 

bool cmp(Edge a,Edge b){return a.R < b.R;}

int lowbit(int x){return x & (-x);}

void insert(int x,int v){
    for(int i=x;i<=n;i+=lowbit(i))
       sum[i] += v;
}

int query(int x){
    int s = 0;
    for(int i=x;i;i-=lowbit(i))
       s += sum[i];
    return s;
}

int main(){
    n = read();
    for(int i=1;i<=n;i++)
        a[i] = read();
    m = read();
    for(int i=1;i<=m;i++){
        e[i].L = read(); 
        e[i].R = read();
        e[i].val = i;
    }
    sort(e + 1 , e + 1 + m , cmp);
    int now = 1;
    for(int i=1;i<=n;i++){
        insert(i , 1);
        if(last[a[i]])  insert(last[a[i]] , -1);
        last[a[i]] = i;
        tmp = query(i);
        while(e[now].R == i && now <= m){
            ans[e[now].val] = tmp - query(e[now].L - 1);
            now++;
        }
    }
    for(int i=1;i<=m;i++)
       printf("%d\n",ans[i]);
    return 0;
}   

 

HH的项链

标签:cstring   owb   ase   ret   iostream   main   根据   树状数组   div   

原文地址:https://www.cnblogs.com/Stephen-F/p/9864581.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!