码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-01-04 11:07:35      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:关键字   接下来   std   poi   line   zoj   href   pre   www   

原题

给定长为 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;
}

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

标签:关键字   接下来   std   poi   line   zoj   href   pre   www   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!