BZOJ1878 SDOI2009 HH的项链 树状数组

题意:给定一个颜色序列,每组询问给出区间[l,r],求[l,r]中不同颜色的数量

题解:

首先把所有颜色离散化,然后离线,将询问按右区间升序排列。从1-N把整个序列扫一遍,设Pos[i]为第i个颜色最后出现的位置,假定当前扫到的位置为i,则更新Pos[a[i]],那么问题变成了:求一个序列(Pos)中,大于等于一个数(L)的数的数量。

用树状数组维护Pos=j的数的数量,每次查询树状数组中L-N的和即可。

貌似SDOI不喜欢考大型数据结构啊……坐等今年打脸

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define lowbit(x) (x&(-x))

const int MAXN=50000+2;
const int MAXM=200000+2;
struct Hash{
    int u,t;
    Hash *Next;
    Hash(){}
    Hash(int _u,int _t,Hash *_Next):u(_u),t(_t),Next(_Next){}
}*Tab[MAXN],mem[MAXM];
int N,M,a[MAXN],cnt,Ans[MAXM],Pos[MAXN],s[MAXN];
map<int,int> m;

void Update(int p,int x){
    while(p<=N) s[p]+=x,p+=lowbit(p);
}

int Sum(int p){
    int Ret=0;
    while(p) Ret+=s[p],p-=lowbit(p);
    return Ret;
}

int main(){
    scanf("%d",&N);
    for(int i=1;i<=N;i++){
        scanf("%d",a+i);
        if(!m[a[i]]) m[a[i]]=++cnt;
        a[i]=m[a[i]];
    }
    scanf("%d",&M),cnt=0;
    for(int i=1,l,r;i<=M;i++){
        scanf("%d %d",&l,&r);
        mem[cnt].u=l,mem[cnt].t=i,mem[cnt].Next=Tab[r],Tab[r]=&mem[cnt],cnt++;
    }

    for(int i=1;i<=N;i++){
        if(Pos[a[i]]) Update(Pos[a[i]],-1);
        Pos[a[i]]=i,Update(i,1);
        for(Hash *p=Tab[i];p;p=p->Next) Ans[p->t]=Sum(N)-Sum(p->u-1);
    }
    for(int i=1;i<=M;i++) printf("%d\n",Ans[i]);

    return 0;
}

时间: 2024-10-28 19:11:13

BZOJ1878 SDOI2009 HH的项链 树状数组的相关文章

[bzoj1878] [SDOI2009]HH的项链(树状数组+离线)

1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3210  Solved: 1619[Submit][Status][Discuss] Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的

\BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1878 题意概括 给出一个长度为n的序列,用m次询问,问区间Li~Ri中有多少种不同的数. 0<=数值<=1000000,n<=50000,m<=200000 题解 本题有许多做法. 这里介绍树状数组和莫队,都是离线算法. 树状数组 我们把序列按照R从小到大排序. 然后从左往右走. 依次加入数字,当前的状态,比如说搞定了前i个数字. 对于第i+1个数字,我们要给它做一个标记,但是不可

BZOJ 1878 SDOI2009 HH的项链 树状数组/莫队算法

题目大意:给定一个序列.求一个区间内有多少个不同的数 正解是树状数组 将全部区间依照左端点排序 然后每次仅仅统计左端点開始的每种颜色的第一个数即可了 用树状数组维护 我写的是莫队算法 莫队明显能搞 m√m明显慢了点可是还是能接受的一个复杂度 一開始离散化数组开小了各种秒RE-- 跪了 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algori

[SDOI2009]HH的项链-树状数组/线段树

树状数组: 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1000010; 4 int id[maxn],tree[maxn],vis[maxn],num[maxn]; 5 int n,m; 6 struct Tree{ 7 int l,r; 8 int pos; 9 }; 10 Tree a[maxn]; 11 int buf[17]; 12 inline void read(int &x){

luogu P1972 [SDOI2009]HH的项链 树状数组

之前只做过分块做法,补一下树状数组做法. 我们先考虑一个问题,如何求从[1,x]这一区间内元素不同的个数?显然我们只要从到到位,遇到一个新的元素,就在对应位置+1,然后使用树状数组求前缀和即可. 这里我们需要去求[x,y],所求区间的左端点也会发生变化.我们先按照[1,x]的方法预处理出这个前缀和数组.我们考虑对询问区间按照左端点排序.然后对于当前的区间[x0,y0],query(y0) - query(x0 - 1)与正确答案相比有所区别,是因为有些元素在x0左侧计算过了,而在这段区间中,对应

BZOJ 1878 SDOI 2009 HH的项链 树状数组 + 离线处理

题目大意:有一些珠子串成的项链,珠子有不同的颜色.多次询问一段区间内有多少不同的颜色. 思路:这个题让我学会了一种巧妙的离线做法.将问题按左端点排序.处理出来每个颜色第一个出现的位置,和每个颜色下一个出现的位置.然后1到cnt循环,如果这里有一个问题的左端点是当前节点,就处理他的答案,方法是前缀合,可以用树状数组.然后把这个颜色的下一个出现的位置+1. 这样做就避免了一种颜色在询问中被处理两次. CODE: #include <cstdio> #include <cstring>

bzoj 1878 HH的项链 (树状数组+离线)

题目大意:给你一个序列,求某区间出现不同的数的个数. 貌似离线树状数组是最好的解法 先把所有询问挂在它们询问的右端点上 然后从头到尾遍历这个序列,记录这个位置的值上一次出现的位置 那么,当遍历到第i位时,如果a[i]在之前出现过,就在它上一次出现的位置-1 这个操作的意义是,第i位已经有a[i]了,那么上一次出现a[i]的位置已经失去意义 接着在这个位置+1,更新last[a[i]].差分操作用树状数组维护 然后我们遍历以这个位置为结尾的所有询问,用树状数组查前缀和,因为在a[i]相同的位置不会

【树状数组】Bzoj1878[SDOI2009] HH的项链

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

BZOJ 1878 SDOI 2009 HH项链 树状数组 + 脱机处理

标题效果:一些珠子项链.珠具有不同的颜色.我们问了很多次有多少种不同的颜色有过一段范围. 思考:这个问题让我学会聪明的离线实践.按左端点排序问题.加工出来的位置每种颜色首次出现.每一种颜色的下一次出现的位置.然后,1至cnt周期,这里有一个问题的左端点是当前节点,就处理他的答案.方法是前缀合,能够用树状数组.然后把这个颜色的下一个出现的位置+1. 这样做就避免了一种颜色在询问中被处理两次. CODE: #include <cstdio> #include <cstring> #in