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不断地收集新的贝壳,因此他的项链变得 ...
随机推荐
- C# Winform继承窗体打开设计器白屏的一例解决方法
环境VS2017 15.5.4,Win10开发过程中,发现一些窗体打开设计器会卡死白屏,另外有一些不会,(两者运行时正常),最小化vs后甚至能把工具箱连带搞黑,严重影响开发效率,经过一天多的对比研究, ...
- 解决idea中找不到程序包和找不到符号的问题
问题如图: 解决方法: 将三处编码都设置成UTF-8,亲测有效 本人也是拜读大佬博客后解决的: http://www.cnblogs.com/wzhanke/p/4747966.html
- C# 简单线程实例
1.简单线程实例 以及委托(同步委托.异步委托) using System; using System.Collections.Generic; using System.Linq; using Sy ...
- JavaScript之12306自动刷新车票[待完善]
function refresh(){ var search_btn = document.getElementById("query_ticket"); var result_t ...
- MSSQL-SELECT&UPDATE动作要申请的锁
最近在学习[MySQL事务&锁]这块知识,一不留神和MSSQL乱窜了~.~ 文章最初是想查看MySQL vs MSSQL在下面环境产生的阻塞现象会话1开启事务更新数据尚未提交->会话2读 ...
- Linux注销&登陆
⒈注销 ①在命令行使用logout,此指令在图形界面无效.
- Docker相关
1.理念 通过对应用组件的封装.分发.部署.运行等生命周期的管理,使用户的App(可以是一个Web应用或数据库应用等)及其运行环境能够做到“一次封装,处处运行”. 2.一句话总结 解决运行环境和配置问 ...
- Django配置富文本编辑器kindeditor
一.简介 django是一个容易快速上手的web框架,用它来创建内容驱动型的网站(比如独立博客)十分方便.遗憾的是,django并没有提供官方的富文本编辑器,而后者恰好是内容型网站后台管理中不可或缺的 ...
- Linux内存管理4---虚拟地址空间管理
1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...
- Linux mmc framework2:基本组件之block
1.前言 本文主要block组件的主要流程,在介绍的过程中,将详细说明和block相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API 2.1 struct mmc_ca ...