BZOJ 1878: [SDOI2009]HH的项链

二次联通门 : BZOJ 1878: [SDOI2009]HH的项链

/*
    BZOJ 1878: [SDOI2009]HH的项链
    

    莫队水过
    
    记录一个count数组
    来记录每个数出现了几次

    缩小区间时只要看是否只出现一次

    扩张区间时只要看看是否出现过即可
    
*/
#include <algorithm>
#include <cstdio>
#include <cmath>

#define Max 1000001

void read (int &now)
{
    now = 0;
    register char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}

int belong[Max];

struct Query_Data
{
    int l, r;

    int Id;
    
    bool operator < (const Query_Data &now) const
    {
        if (belong[now.l] == belong[this->l])
            return this->r < now.r;
        else
            return belong[this->l] < belong[now.l];
    }
};


int N, M;

int number[Max];
Query_Data query[Max];

int count[Max];

int Result;

bool visit[Max];

inline void Updata (int now, bool type) 
{
    if (type)
    {
        if (!count[number[now]])
            Result ++;
        count[number[now]] ++;
    }
    else
    {
        if (count[number[now]] == 1)
            Result --;
        count[number[now]] --;
    }
}

int Answer[Max];

int main (int argc, char *argv[])
{
    read (N);
    int Size = sqrt (N);
    for (int i = 1; i <= N; i ++)
    {
        read (number[i]);
        belong[i] = (i + 1) / Size;
    }
    read (M);
    for (int i = 1; i <= M; i ++)
    {
        read (query[i].l);
        read (query[i].r);
        query[i].Id = i;
    }
    std :: sort (query + 1, query + 1 + M);
    int l = 1, r = 0;
    for (int i = 1; i <= M; i ++)
    {
        if (l < query[i].l)
            for (int pos = l; pos < query[i].l; pos ++)
                Updata (pos, false);
        else if (l >= query[i].l)
            for (int pos = l - 1; pos >= query[i].l; pos --)
                Updata (pos, true);
        if (r > query[i].r)
            for (int pos = r; pos > query[i].r; pos--)
                Updata (pos, false);
        else if (r <= query[i].r)
            for (int pos = r + 1; pos <= query[i].r; pos++)
                Updata (pos, true);
        l = query[i].l;
        r = query[i].r;
        Answer[query[i].Id] = Result;
    }
    for (int i = 1; i <= M; i ++)
        printf ("%d
", Answer[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/6947007.html