【题目链接】

https://www.lydsy.com/JudgeOnline/problem.php?id=1878

【算法】

显然,在线算法是不可做的,考虑离线算法

笔者的做法是莫队算法,时间复杂度 : O(nsqrt(n))(sqrt表示开方)

但是,树状数组的效率更高,下面讲一讲这种高效的做法 :

不妨将所有询问按右端点排序

对于每次询问,我们只考虑每种颜色最后出现的一次,用树状数组维护每一个位置是否对答案产生“贡献“

具体来说,我们用一个Next数组记录这种颜色上次出现的位置,然后,对于每个位置i,如果存在Next[i],将树状数组中的Next[i]减1,将这个位置加1即可

时间复杂度 :O(nlog(n))

【代码】

我的代码(莫队) :

#include<bits/stdc++.h>
using namespace std;
#define MAXN 50010
#define MAXS 1000010
#define MAXM 200010 struct Query
{
int l,r;
int id;
} q[MAXM],b[MAXM]; int i,j,k,n,m,block,len,t,sum,l,r;
int a[MAXN],s[MAXS],ans[MAXM]; inline bool cmp1(Query a,Query b)
{
return a.l < b.l;
}
inline bool cmp2(Query a,Query b)
{
return a.r < b.r;
}
inline void add(int l,int r,int val)
{
int i;
for (i = l; i <= r; i++)
{
if (s[a[i]] == && val == -) sum--;
if (s[a[i]] == && val == ) sum++;
s[a[i]] += val;
}
} int main()
{ scanf("%d",&n);
for (i = ; i <= n; i++) scanf("%d",&a[i]);
scanf("%d",&m);
for (i = ; i <= m; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id = i;
}
sort(q+,q+m+,cmp1);
len = (int)sqrt(n);
block = n / len + (n % len != );
j = ;
for (i = ; i <= block; i++)
{
t = ;
sum = ;
while (j <= m && q[j].l > (i - ) * len && q[j].l <= i * len)
{
b[++t] = q[j];
j++;
}
sort(b+,b+t+,cmp2);
l = b[].l; r = b[].l - ;
for (k = ; k <= t; k++)
{
if (l < b[k].l) add(l,b[k].l-,-);
else if (l > b[k].l) add(b[k].l,l-,);
add(r+,b[k].r,);
ans[b[k].id] = sum;
l = b[k].l; r = b[k].r;
}
add(l,r,-);
}
for (i = ; i <= m; i++) printf("%d\n",ans[i]); return ;
}

黄学长的代码(树状数组)

(http://hzwer.com/3007.html)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
int x=;char ch=getchar();
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
}
int n,m,mx;
int a[],next[],t[];
int p[];
struct data{int l,r,id,ans;}q[];
bool cmp1(data a,data b)
{return a.l==b.l?a.r<b.r:a.l<b.l;}
bool cmp2(data a,data b)
{return a.id<b.id;}
int lowbit(int x){return x&(-x);}
void update(int x,int v)
{
for(int i=x;i<=n;i+=lowbit(i))
t[i]+=v;
}
int ask(int x)
{
int tmp=;
for(int i=x;i>;i-=lowbit(i))
tmp+=t[i];
return tmp;
}
int main()
{
n=read();
for(int i=;i<=n;i++)
a[i]=read(),mx=max(mx,a[i]);
for(int i=n;i>;i--)
next[i]=p[a[i]],p[a[i]]=i;
for(int i=;i<=mx;i++)
if(p[i])update(p[i],);
m=read();
for(int i=;i<=m;i++)
q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+,q+m+,cmp1);
int l=;
for(int i=;i<=m;i++)
{
while(l<q[i].l)
{
if(next[l])update(next[l],);
l++;
}
q[i].ans=ask(q[i].r)-ask(q[i].l-);
}
sort(q+,q+m+,cmp2);
for(int i=;i<=m;i++)
printf("%d\n",q[i].ans);
return ;
}

【BZOJ 1878】 HH的项链的更多相关文章

  1. BZOJ 1878 hh的项链(简单莫队)

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

  2. BZOJ 1878 HH的项链(树状数组)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1878 题意:给出一个数列,每次询问区间[L,R]中有多少个不同的数字? 思路: (1)记 ...

  3. BZOJ 1878 HH的项链

    不能分块(显然复杂度会炸啊.....) 离线+BIT.每个颜色在每个询问中只出现一次. #include<iostream> #include<cstdio> #include ...

  4. BZOJ 1878 HH的项链 | 主席树

    题意 询问区间有多少不同的数. 题解 和Luogu 1903一样,这道题也是用pre数组来求区间不同数的个数,这里pre[i]表示a[i]上一次出现的位置 +1,询问相当于查询区间内有多少pre小于等 ...

  5. [bzoj] 1878 HH的项链 || 莫队

    原题 给定长为 n 的一个序列,接下来 m 次询问,每次询问区间 [ l , r ] 内有多少个不同的数. 莫队: 离线\(O(n\log(n))\). 将序列分块. 以左端点所在块为第一关键字,右端 ...

  6. BZOJ 1878 HH的项链 (树状数组+离线)

    题目大意:给你一个序列,求某区间出现不同的数的个数. 貌似离线树状数组是最好的解法 先把所有询问挂在它们询问的右端点上 然后从头到尾遍历这个序列,记录这个位置的值上一次出现的位置 那么,当遍历到第i位 ...

  7. Codevs 2307[SDOI2009]HH的项链

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

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

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

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

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

  10. BZOJ 1878: [SDOI2009]HH的项链 离线树状数组

    1878: [SDOI2009]HH的项链 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

随机推荐

  1. A - Translation

    Problem description The translation from the Berland language into the Birland language is not an ea ...

  2. [转]解决C# WinForm 中 VSHOST.EXE 程序不关闭的问题

    右击“解决方案”--属性-调试栏-启用调试器部分-“启用Visual studio宿主进程”不勾选

  3. 「JavaSE 重新出发」05.03.03 使用反射编写泛型数组代码

    Employee[] a = new Employee[100]; // ... // array is full a = Arrays.copyOf(a, 2 * a.length); 如何编写这样 ...

  4. 《SLIC Superpixels》阅读笔记

    原始链接:http://blog.csdn.net/jkhere/article/details/16819285 或许有改动,请参考原文! SLIC 超像素(SLICSuperpixels) Rad ...

  5. 杭电 1012 u Calculate e【算阶乘】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1012 解题思路:对阶乘递归求和 反思:前面3个的输出格式需要注意,可以自己单独打印出来,也可以在for ...

  6. yii处理cookie

    /** * 设置用户cookie会话 */ public function setCookie() { //set loginName $cookies = Yii::app()->reques ...

  7. Jquery 研究 入口

    <script type="text/javascript"> //var jQuery = function () { // console.log(jQuery.f ...

  8. 详解优动漫PAINT中的图层模式

    使用优动漫PAINT绘制漫画或者插画的时候,在其新建画布区域有一个基本颜色模式的选项,分别包括彩色模式.灰度模式和黑白位图模式,那么这三个模式有什么区别呢,我们在绘图的时候应该如何选择呢? 彩色模式: ...

  9. new String(getBytes(ISO-8859-1),UTF-8)中文编码避免乱码

    byte[] b_gbk = "深".getBytes("GBK"); byte[] b_utf8 = "深".getBytes(" ...

  10. a标记地址的几种用法

    1.<a href="tel://号码"></a> 手机使用能自动拨打电话 //可以省略 2.<a href="mailto://邮箱&qu ...