洛谷 P1972 [SDOI2009]HH的项链

题意简述

给定一个序列
给出多个询问(l,r),求出l~r有多少不同的数字

题解思路

莫队,注意要奇偶块排序

代码

#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
struct Node
{
    int l, r, i;
} q[500100];
int n, m, len, ll, lr, s;
int a[500100], num[500100], c[1000100], ans[500100];
const int ri_top = 2e7;
char ri[ri_top], *rich = ri;
void read_int(int &x)
{
    while (!isdigit(*rich)) ++rich;
    for (x = *rich - '0'; isdigit(*++rich); x = x * 10 + *rich - '0');
}
const int wi_top = 2e7;
char wi[wi_top], *wich = wi;
const int wi_top1 = 11;
char wi1[wi_top1], *wich1 = wi1;
void write_int(int x)
{
    if (!x) {*wich++ = '0'; return;}
    for (; x; *wich1++ = x % 10 + '0', x /= 10);
    while (wi1 != wich1) *wich++ = *--wich1;
}
struct _
{
    __inline__ __attribute((always_inline)) bool operator()(const Node& x, const Node& y)
    {
        return num[x.l] < num[y.l] || num[x.l] == num[y.l] && ((num[x.l] & 1) ? x.r < y.r : x.r > y.r);
    }
}cmp;
int main()
{
    fread(ri, 1, ri_top, stdin);
    read_int(n);
    len = sqrt(n);
    for (register int i = 1; i <= n; ++i)
    {
        read_int(a[i]);
        num[i] = (i - 1) / len + 1;
    }
    read_int(m);
    for (register int i = 1; i <= m; ++i)
    {
        read_int(q[i].l);
        read_int(q[i].r);
        q[i].i = i;
    }
    sort(q + 1, q + m + 1, cmp);
    for (register int i = 1; i <= m; ++i)
    {
        int l = q[i].l, r = q[i].r;
        while (l < ll) s += !(c[a[--ll]]++);
        while (r > lr) s += !(c[a[++lr]]++); 
        while (l > ll) s -= !(--c[a[ll++]]);
        while (r < lr) s -= !(--c[a[lr--]]);
        ans[q[i].i] = s;
    }
    for (register int i = 1; i <= m; ++i)
        write_int(ans[i]), *wich++ = '\n';
    fwrite(wi, 1, wich - wi, stdout);
}
posted @ 2018-08-21 20:43  xuyixuan  阅读(120)  评论(0编辑  收藏  举报