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

原题

给定长为 n 的一个序列,接下来 m 次询问,每次询问区间 [ l , r ] 内有多少个不同的数。



莫队:
离线\(O(n\log(n))\)。
将序列分块。
以左端点所在块为第一关键字,右端点位置为第二关键字sort,然后two-points移动暴力记录即可。

#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 50010
#define M 200010
using namespace std;
int n,m,ans[M],tot,a[N],cnt[1000010],s,l,r;

int bel(int x) { return ((x-1)/s+1); }

struct hhh
{
    int x,y,id;
    bool operator < (const hhh &b) const
    {
        if (bel(x)==bel(b.x)) return y<b.y;
        return bel(x)<bel(b.x);
    }
}q[M];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
    for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
    return ans*fu;
}

int main()
{
    n=read();s=sqrt(n);
    for (int i=1;i<=n;i++)
    a[i]=read();
    m=read();
    for (int i=1;i<=m;i++) q[i].x=read(),q[i].y=read(),q[i].id=i;
    sort(q+1,q+m+1);
    for (int i=1;i<=m;i++)
    {
    while (l<q[i].x) if (!--cnt[a[l++]]) tot--;
    while (l>q[i].x) if (!cnt[a[--l]]++) ++tot;
    while (r<q[i].y) if (!cnt[a[++r]]++) ++tot;
    while (r>q[i].y) if (!--cnt[a[r--]]) tot--;
    ans[q[i].id]=tot;
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/mrha/p/8191331.html

时间: 2024-10-01 07:21:45

[bzoj] 1878 HH的项链 || 莫队的相关文章

BZOJ 1878: [SDOI2009]HH的项链 | 莫队

题解: http://www.lydsy.com/JudgeOnline/problem.php?id=1878 题解: 莫队板子题 核心思想是对区间的询问离线之后按照合理的顺序来优化复杂度 一般的做法是先分块,以左端点所在块为第一关键字,右端点位置为第二关键字排序 用两个指针来跑,这样可以证明的是时间复杂度为O(n√n) #include<cstdio> #include<algorithm> #include<cstring> #include<cmath&g

[BZOJ1878][SDOI2009]HH的项链 莫队

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1878 不带修改的莫队,用一个桶记录一下当前区间中每种颜色的数量就可以做到$O(1)$更新了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 int inline readint(){ 7 i

[SDOI2009][bzoj1878] HH的项链 [莫队模板题]

题面: 传送门 思路: 就是一道莫队的模板题目...... 开一个1000000的数组记录每个数出现的次数,然后每次从1到0或者从0到1更新答案 莫队讲解看这里:莫队 Code: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 inline int

BZOJ 1878 HH的项链

不能分块(显然复杂度会炸啊.....) 离线+BIT.每个颜色在每个询问中只出现一次. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 50050 #define maxm 200050 #define maxc 1000500 using namespace std; int n,a[maxn],aft[maxn],pre[maxn

BZOJ 1878 HH的项链(主席树)

对于该题,离线的做法是树状数组或者线段树. 如果强制在线的话,可以用主席树做到O(mlogn). 考虑到这样一个性质,对于询问[l,r]出现的数字种数.其答案就是to[i]>r的数字数. 其中to[i]表示的是第i个数的下一个相同的数出现的下标,没有则=n+1. 很幸运这个性质是满足区间减法的,也就是说对于[1,r]和[1,l-1]的to[i]域,是可以相减得到[l,r]的to[i]域的. 于是我们可以用主席树来解决这个问题. 对于一组询问,实际上就是求[l-1,r]这颗线段树上的区间[r+1,

bzoj 1878 HH的项链 (树状数组+离线)

题目大意:给你一个序列,求某区间出现不同的数的个数. 貌似离线树状数组是最好的解法 先把所有询问挂在它们询问的右端点上 然后从头到尾遍历这个序列,记录这个位置的值上一次出现的位置 那么,当遍历到第i位时,如果a[i]在之前出现过,就在它上一次出现的位置-1 这个操作的意义是,第i位已经有a[i]了,那么上一次出现a[i]的位置已经失去意义 接着在这个位置+1,更新last[a[i]].差分操作用树状数组维护 然后我们遍历以这个位置为结尾的所有询问,用树状数组查前缀和,因为在a[i]相同的位置不会

bzoj 3757: 苹果树(树上莫队)

3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 1327  Solved: 510 [Submit][Status][Discuss] Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色.我们用一个1到n之间的正整数来表示一种颜色

【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

学习了树上莫队,树分块后对讯问的$dfs序$排序,然后就可以滑动树链处理答案了. 关于树链的滑动,只需要特殊处理一下$LCA$就行了. 在这里一条树链保留下来给后面的链来转移的$now$的为这条树链上所有点除去$LCA$的颜色种数.因为如果要考虑$LCA$情况就太多了,不如单独考虑$LCA$. 转移后加上当前链的$LCA$进行统计,然后再去掉这个$LCA$更新一下$now$值给后面的链转移. 这都是我的理解,说的有点不清楚,具体请看vfk的题解 OTZ 虽然不是这道题,但是通过这篇博客学习树上莫

BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mat