BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队
欢迎访问~原文出处——博客园-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的项链 树状数组 或 莫队的更多相关文章
- luogu P1972 [SDOI2009]HH的项链 |树状数组 或 莫队
题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...
- [BZOJ1878] [SDOI2009] HH的项链 (树状数组)
Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变 ...
- bzoj1878 [SDOI2009]HH的项链——树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1878 离线树状数组,巧妙的思路呢: 给每种项链记录一个最后出现的位置lst,根据项链最后出现 ...
- BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]
1878: [SDOI2009]HH的项链 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3486 Solved: 1738[Submit][Statu ...
- BZOJ1878: [SDOI2009]HH的项链[树状数组+离线 | 主席树]
题意: 询问区间不同种类颜色数 [2016-11-15] 离线好厉害 对于每一个区间询问,一个数只考虑一次,那么考虑他最后出现的一次 将询问按r排序 从1到n扫描,用树状数组维护一个位置应不应该考虑( ...
- 【bzoj1878】[SDOI2009]HH的项链 树状数组
题目描述 HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一 ...
- 【bzoj1878】[SDOI2009]HH的项链 - 树状数组 - 离线处理
[SDOI2009]HH的项链 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 4834 Solved: 2384[Submit][Status][Dis ...
- 【题解】P1972 [SDOI2009]HH的项链 - 树状数组
P1972 [SDOI2009]HH的项链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 \(HH\) 有一串由各种 ...
- bzoj 1878: [SDOI2009]HH的项链 ——树状数组+ 差分
Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此他的项链变得 ...
随机推荐
- Keil5下载STM32库
1.http://www.keil.com/dd2 2.3.以STM32L051C8为例 下载即可.
- CSS cursor 属性改变鼠标的样式
可能的值 值 描述 url 需使用的自定义光标的 URL. 注释:请在此列表的末端始终定义一种普通的光标,以防没有由 URL 定义的可用光标. default 默认光标(通常是一个箭头) auto 默 ...
- dubbo服务使用spring-data-mongodb进行时间查询的bug记录
一.项目情况:spring-boot+mongodb+dubbo. 二.问题:调用dubbo服务并使用spring-data-mongodb的gte,lte时间段比较查询, @Reference(re ...
- UML和模式应用4:初始阶段(6)--迭代方法中如何使用用例
1.前言 用例是UP和其他众多迭代方法的核心.UP提倡用例驱动开发. 2. 迭代方法中如何使用用例 功能需求首先定义在用例中 用例是迭代计划的重要部分,迭代是通过选择一些用例场景或整个用例来定义的 用 ...
- ES系列十七、logback+ELK日志搭建
一.ELK应用场景 在复杂的企业应用服务群中,记录日志方式多种多样,并且不易归档以及提供日志监控的机制.无论是开发人员还是运维人员都无法准确的定位服务.服务器上面出现的种种问题,也没有高效搜索日志内容 ...
- 一步步实现windows版ijkplayer系列文章之三——Ijkplayer播放器源码分析之音视频输出——音频篇
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- elk系统通过nginx添加对kibana的登录认证
elk系统添加对kibana的登录认证 关于elk系统的安装配置可以参考:Centos6.5安装Logstash ELK stack 日志管理系统及使用详解 http://blog.csdn.net/ ...
- zabbix系列(四)Zabbix3.0.4添加对Nginx服务的监控
Zabbix3.0.4添加对Nginx服务的监控 通过Nginx的http_stub_status_module模块提供的状态信息来监控,所以在Agent端需要配置Nginx状态获取的脚本,和添加ke ...
- sqlserver2008r2通过发布和订阅的方式进行数据库同步
发布服务器:192.168.8.16 订阅服务器:192.168.8.92 发布服务器配置: 选择需要发布的数据库,这里是Attendace_new 订阅服务器配置: 在订阅服务器上新建一个数据库:d ...
- CentOS 6.5使用Corosync + pacemaker实现httpd服务的高可用
Corosync:它属于OpenAIS(开放式应用接口规范)中的一个项目corosync一版本中本身不具备投票功能,到了corosync 2.0之后引入了votequorum子系统也具备了投票功能了, ...