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。

题解

这题首先在线是没法做的,所以我们可以考虑离线算法

解法1:莫队裸题,分块就好。

 #include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define RE register
#define IL inline
using namespace std;
const int M=;
const int N=;
const int Q=; int cnt[M+],ans;
int keep[Q+];
int n,m,a[N+],tim;
struct query
{
int l,r,id;
}q[Q+];
bool comp(const query &a,const query &b){return a.l/tim==b.l/tim ? a.r<b.r:a.l<b.l;} int main()
{
scanf("%d",&n);
tim=sqrt(n);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
for (int i=;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+,q+m+,comp);
int curl=,curr=,l,r;
for (int i=;i<=m;i++)
{
l=q[i].l,r=q[i].r;
while (curl<l) {cnt[a[curl]]--;ans-=(cnt[a[curl++]]==);}
while (curl>l) {cnt[a[--curl]]++;ans+=(cnt[a[curl]]==);}
while (curr<r) {cnt[a[++curr]]++;ans+=(cnt[a[curr]]==);}
while (curr>r) {cnt[a[curr]]--;ans-=(cnt[a[curr--]]==);}
keep[q[i].id]=ans;
}
for (int i=;i<=m;i++) printf("%d\n",keep[i]);
return ;
}

莫队

解法2:排序+树状数组。

首先记录下每种颜色的下一种颜色所在的位置,将所有询问按照右端点进行排序。

左往右扫,扫过一个元素将该位置++,若有前驱,将前驱--。

扫到区间端点,答案为$sum[r]-sum[l-1]$,记录一下就好。(其中$sum$为前缀和)

前缀和用树状数组实现。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct Node
{
int l,r,num;
}s[];
int a[],ans[],n,m,c[],vis[];
bool cmp(Node a,Node b)
{
return (a.r<b.r||(a.r==b.r&&a.l<b.l));
}
int getsum(int x)
{
int s=;
while (x)
{
s+=c[x];
x-=(x&(-x));
}
return s;
}
void add(int x,int d)
{
while (x<=n)
{
c[x]+=d;
x+=(x&(-x));
}
}
int main()
{int i,j;
cin>>n;
for (i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
cin>>m;
for (i=;i<=m;i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
s[i].num=i;
}
sort(s+,s+m+,cmp);
j=;
for (i=;i<=n+;i++)
{
while (j<=m&&i>s[j].r)
{
ans[s[j].num]=getsum(s[j].r)-getsum(s[j].l-);
j++;
}
if (i>n) break;
if (vis[a[i]])
{
add(vis[a[i]],-);
vis[a[i]]=i;
add(i,);
}
else
{
vis[a[i]]=i;
add(i,);
}
}
for (i=;i<=m;i++)
printf("%d\n",ans[i]);
}

排序+树状数组

[SDOI 2009]HH的项链的更多相关文章

  1. [ SDOI 2009 ] HH的项链 & [ HEOI 2012 ] 采花

    \(\\\) \(Description\) 给出一个长为\(N\)的序列,\(M\)次询问区间\([L_i,R_i]\)内不同数字的个数. \(N\in [1,5\times 10^4]\),\(M ...

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

    标题效果:一些珠子项链.珠具有不同的颜色.我们问了很多次有多少种不同的颜色有过一段范围. 思考:这个问题让我学会聪明的离线实践.按左端点排序问题.加工出来的位置每种颜色首次出现.每一种颜色的下一次出现 ...

  3. [SDOI 2009]HH去散步

    Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...

  4. [BZOJ 1875] [SDOI 2009] HH去散步【矩阵乘法】

    题目链接:BZOJ - 1875 题目分析: 这道题如果去掉“不会立刻沿着刚刚走来的路走回”的限制,直接用邻接矩阵跑矩阵乘法就可以了.然而现在加了这个限制,建图的方式就要做一些改变.如果我们把每一条边 ...

  5. sdoi 2009 HH去散步 矩阵乘

    如果没有题里的"不会立刻沿着刚刚走来的路走回"限制,那么直接矩乘计算k步的方案数 但加了这个限制,就不能以点来矩乘了,考虑边数<=60,如果以边建邻接矩阵呢?? 先拆边,再把 ...

  6. Codevs 2307[SDOI2009]HH的项链

    同题:     Codevs 2307 HH的项链     BZOJ    1878 HH的项链     洛谷      1972 HH的项链 2009年省队选拔赛山东  时间限制: 1 s  空间限 ...

  7. BZOJ 1878: [SDOI2009]HH的项链

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3548  Solved: 1757[Submit][Statu ...

  8. BZOJ-1878 HH的项链 树状数组+莫队(离线处理)

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 2701 Solved: 1355 [Submit][Statu ...

  9. 【BZOJ】【1878】【SDOI2009】HH的项链

    树状数组/前缀和 Orz lct1999 好神的做法... 先看下暴力的做法:对于区间[l,r],我们依次扫过去,如果这个数是第一次出现,那么我们种类数+1. 我们发现:区间中相同的几个数,只有最左边 ...

随机推荐

  1. String s=new String("abc")创建了几个对象?

    String str=new String("abc");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢? 答案应该是1个或者2个. 1个 ...

  2. alpha冲刺总结随笔

    前言:前面乱乱糟糟整了一路,到最后终于可以稳定下来了.安安心心做个总结,然后把之后要做的事情都理清楚好了. 新学长似乎是个正经[并不]大腿. 看起来也不用都是一个人或者跟陈华学长两个人对半开了[突然摸 ...

  3. C语言最后一次作业——总结报告

    1.当初你是如何做出选择计算机专业的决定的?经过一个学期,你的看法改变了么,为什么? 你觉得计算机是你喜欢的领域吗,它是你擅长的领域吗? 为什么? 首先是因为自己想学跟做动画沾边的专业(动画专业因为某 ...

  4. V7000存储数据恢复_底层结构原理拆解及Mdisk磁盘掉线数据恢复方法

    Storwize V7000(也就是我们常说的V7000)是新推出的一款中端存储系统,这款系统的定位虽然在中端,但是Storwize V7000提供有存储管理功能,这一功能以前只有高端存储才拥有(例如 ...

  5. nyoj 正数性质

    整数性质 时间限制:500 ms  |  内存限制:65535 KB 难度:1   描述 我们知道,在数学中,对于任意两个正整数a和b,必定存在一对整数s.t使得sa+tb=gcd(a,b).   输 ...

  6. C语言头文件引用

    1,引用分为两种 firs:include<fileName.h> 引用系统头文件一般用<>. second:include"fileName.h" 引用自 ...

  7. 可空类型 Nullable<T>

    Nullable<T> 内部实现了显示和隐式转换 显示转换: public static explicit operator T(T? value) { return value.Valu ...

  8. PHP环境配置(1)

    Apache下载 Apache下载地址:http://httpd.apache.org/download.cgi 第一步:点击Files for Microsoft Windows 第二步:点击Apa ...

  9. 前端插件之Bootstrap Switch 选择框开关控制

    简介 Bootstrap Switch是一款轻量级插件,可以给选择框设置类似于开关的样式 它是依赖于Bootstrap的一款插件 下载 下载地址 在线引用 导入 因为它是依赖于Bootstrap的一款 ...

  10. Mysql 5.1的坑

    1.数据库表是区分大小写的 之前程序在5.7数据库没问题,测试环境上数据库是5.1的,就提示表找不到. 2.同样的sql,在5.1上会提示事务获取锁失败,超时返回.而5.7上正常.原因暂未找到.