欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1878


题意概括

  给出一个长度为n的序列,用m次询问,问区间Li~Ri中有多少种不同的数。

  0<=数值<=1000000,n<=50000,m<=200000


题解

  本题有许多做法。

  这里介绍树状数组和莫队,都是离线算法。

  树状数组

  我们把序列按照R从小到大排序。

  然后从左往右走。

  依次加入数字,当前的状态,比如说搞定了前i个数字。

  对于第i+1个数字,我们要给它做一个标记,但是不可以重复,那么最优的方案就是把它之前的那个位置的+1标记删除,放到这里来。

  于是对于搞定前i个数的时候,有且一定有对于某一个数值,如果它出现过,那么它的+1标记在最后出现的那个地方。

  为什么可以?因为R是递增的!

  然后就是维护一个点修改和区间和的东西了。秒选树状数组。

  莫队

  莫队就是最裸的莫队。

  先把1~n的区间尽量平均的分成sqrt(n)块。

  把所有的询问以L所在的块为第一关键字升序,R为第二关键字升序排序。

  然后就是大暴力。

  朴素的写法有点长。

  但是压缩之后短的无厘头……


代码

  代码1 - 树状数组

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=50000+5,M=200000+5,V=1000000+5;
int n,m,a[N],c[N],pos[V];
struct Query{
int L,R,bh,ans;
bool operator < (const Query x) const {
return R<x.R;
}
}q[M];
bool cmpbh(Query a,Query b){
return a.bh<b.bh;
}
int lowbit(int x){
return x&-x;
}
void add(int x,int d){
if (!x)
return;
for (;x<=n;x+=lowbit(x))
c[x]+=d;
}
int sum(int x){
int ans=0;
for (;x>0;x-=lowbit(x))
ans+=c[x];
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for (int i=1;i<=m;i++){
scanf("%d%d",&q[i].L,&q[i].R);
q[i].bh=i;
}
sort(q+1,q+m+1);
memset(pos,0,sizeof pos);
memset(c,0,sizeof c);
for (int i=1,j=0;i<=m;i++){
while (j<q[i].R){
j++;
add(pos[a[j]],-1);
pos[a[j]]=j;
add(pos[a[j]],1);
}
q[i].ans=sum(q[i].R)-sum(q[i].L-1);
}
sort(q+1,q+m+1,cmpbh);
for (int i=1;i<=m;i++)
printf("%d\n",q[i].ans);
return 0;
}

  代码2 - 莫队

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=50000+5,M=200000+5,V=1000000+5;
int n,m,size,a[N],cnt[V];
struct Query{
int L,R,bh,ans;
}q[M];
bool cmpmd(Query a,Query b){
int k1=a.L/size,k2=b.L/size;
if (k1!=k2)
return k1<k2;
return a.R<b.R;
}
bool cmpbh(Query a,Query b){
return a.bh<b.bh;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for (int i=1;i<=m;i++){
scanf("%d%d",&q[i].L,&q[i].R);
q[i].bh=i;
}
size=sqrt(n)+0.5;
memset(cnt,0,sizeof cnt);
sort(q+1,q+m+1,cmpmd);
for (int i=1,tot=0,L=1,R=0;i<=m;i++){
while (R<q[i].R){
R++;
if (cnt[a[R]]==0)
tot++;
cnt[a[R]]++;
}
while (L>q[i].L){
L--;
if (cnt[a[L]]==0)
tot++;
cnt[a[L]]++;
}
while (R>q[i].R){
cnt[a[R]]--;
if (cnt[a[R]]==0)
tot--;
R--;
}
while (L<q[i].L){
cnt[a[L]]--;
if (cnt[a[L]]==0)
tot--;
L++;
}
q[i].ans=tot;
}
sort(q+1,q+m+1,cmpbh);
for (int i=1;i<=m;i++)
printf("%d\n",q[i].ans);
return 0;
}

  代码3 - 莫队+代码压缩

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=50000+5,M=200000+5,V=1000000+5;
int n,m,size,a[N],cnt[V];
struct Query{
int L,R,bh,ans;
}q[M];
bool cmpmd(Query a,Query b){
int k1=a.L/size,k2=b.L/size;
if (k1!=k2)
return k1<k2;
return a.R<b.R;
}
bool cmpbh(Query a,Query b){
return a.bh<b.bh;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for (int i=1;i<=m;i++)
scanf("%d%d",&q[i].L,&q[i].R),q[i].bh=i;
size=sqrt(n)+0.5;
memset(cnt,0,sizeof cnt);
sort(q+1,q+m+1,cmpmd);
for (int i=1,tot=0,L=1,R=0;i<=m;i++){
while (R<q[i].R)
tot+=cnt[a[++R]]++==0;
while (L>q[i].L)
tot+=cnt[a[--L]]++==0;
while (R>q[i].R)
tot-=--cnt[a[R--]]==0;
while (L<q[i].L)
tot-=--cnt[a[L++]]==0;
q[i].ans=tot;
}
sort(q+1,q+m+1,cmpbh);
for (int i=1;i<=m;i++)
printf("%d\n",q[i].ans);
return 0;
}

  

BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队的更多相关文章

  1. luogu P1972 [SDOI2009]HH的项链 |树状数组 或 莫队

    题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...

  2. [BZOJ1878] [SDOI2009] HH的项链 (树状数组)

    Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变 ...

  3. bzoj1878 [SDOI2009]HH的项链——树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1878 离线树状数组,巧妙的思路呢: 给每种项链记录一个最后出现的位置lst,根据项链最后出现 ...

  4. BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]

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

  5. BZOJ1878: [SDOI2009]HH的项链[树状数组+离线 | 主席树]

    题意: 询问区间不同种类颜色数 [2016-11-15] 离线好厉害 对于每一个区间询问,一个数只考虑一次,那么考虑他最后出现的一次 将询问按r排序 从1到n扫描,用树状数组维护一个位置应不应该考虑( ...

  6. 【bzoj1878】[SDOI2009]HH的项链 树状数组

    题目描述 HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一 ...

  7. 【bzoj1878】[SDOI2009]HH的项链 - 树状数组 - 离线处理

    [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4834  Solved: 2384[Submit][Status][Dis ...

  8. 【题解】P1972 [SDOI2009]HH的项链 - 树状数组

    P1972 [SDOI2009]HH的项链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 \(HH\) 有一串由各种 ...

  9. bzoj 1878: [SDOI2009]HH的项链 ——树状数组+ 差分

    Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此他的项链变得 ...

随机推荐

  1. IDEA不生成WAR包,报错

    com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionExceptionProjec ...

  2. 多文档界面QMdiArea

    当使用多文档界面功能时,我们是将QMdiArea作为主窗口的中央部件,然后在这个中央部件中,我们可以同时打开很多个子窗口QMdiSubWindow 样式: import sys from PyQt5. ...

  3. centos6 python 安装 sqlite 解决 No module named ‘_sqlite3′

    原文连接: http://blog.csdn.net/jaket5219999/article/details/53512071 系统red hat6.7 也即centos6.7 python3.5. ...

  4. mysql 案例~mysql主从复制延迟处理(2)

    一 简介:今天来聊聊周期性从库延迟的问题,是上一篇的基础分析的一个场景 二 背景:近期每天的指定时间段,收到从库延迟的报警,然后过一段时间恢复.由于从库是提供读服务的,所以需要解决 三 分析思路: 1 ...

  5. ubuntu14.04 提示 卷 文件系统根目录 仅剩余xxx的硬盘空间

  6. freeRTOS中文实用教程3--中断管理之延迟中断处理

    1.前言 嵌入式实时操作系统需要对整个系统环境产生的事件作出响应.可以采用中断方式也可以采用轮询方式来进行处理.如果采用中断方式,则希望ISR(中断服务例程)的处理时间越短越好. 注:必须说明的是,只 ...

  7. Epoll模型

    Epoll模型 相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率.因为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多.并且,在l ...

  8. OpenWrt启动过程分析+添加自启动脚本【转】

    一.OpenWrt启动过程分析 转自: http://www.eehello.com/?post=107 总结一下OpenWrt的启动流程:1.CFE->2.linux->3./etc/p ...

  9. SQLServer语言之DDL,DML,DCL,TCL

    数据库语言分类 SQLServer   SQL主要分成四部分: (1)数据定义.(SQL DDL)用于定义SQL模式.基本表.视图和索引的创建和撤消操作. (2)数据操纵.(SQL DML)数据操纵分 ...

  10. Coursera台大机器学习技法课程笔记07-Blending and Bagging

    这一节讲如何将得到的feature或hypothesis组合起来用于预测. 1. 林老师给出了几种方法 在选择g时,需要选择一个很强的g来确保Eval最小,但如果每个g都很弱该怎么办呢 这个时候可以选 ...