luogu P1972 [SDOI2009]HH的项链

二次联通门 : luogu P1972 [SDOI2009]HH的项链

/*
    luogu P1972 [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\n", Answer[i]);
    return 0;
}
时间: 2024-08-07 07:56:22

luogu P1972 [SDOI2009]HH的项链的相关文章

【题解】Luogu P1972 [SDOI2009]HH的项链

原题传送门 莫队入门题 我博客里对莫队的介绍 很多人说这题卡莫队,但窝随便写了一个程序就过了qaq(虽说开了氧化) 我们在排序询问时,普通是这样qaq inline bool cmp(register query a,register query b) { return a.bl==b.bl?a.r<b.r:a.bl<b.bl; } 我们要奇偶优化:按奇偶块排序.如果区间左端点所在块不同,那么就直接按左端点从小到大排:如果相同,奇块按右端点从小到大排,偶块按右端点从大到小排. inline b

luogu P1972 [SDOI2009]HH的项链 树状数组

之前只做过分块做法,补一下树状数组做法. 我们先考虑一个问题,如何求从[1,x]这一区间内元素不同的个数?显然我们只要从到到位,遇到一个新的元素,就在对应位置+1,然后使用树状数组求前缀和即可. 这里我们需要去求[x,y],所求区间的左端点也会发生变化.我们先按照[1,x]的方法预处理出这个前缀和数组.我们考虑对询问区间按照左端点排序.然后对于当前的区间[x0,y0],query(y0) - query(x0 - 1)与正确答案相比有所区别,是因为有些元素在x0左侧计算过了,而在这段区间中,对应

P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链 2017-09-18 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答--因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行:N 个整

洛谷 P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行:N 个整数,表示

树状数组--P1972 [SDOI2009]HH的项链

题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. 有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答…… 因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入格式 一行一个正整数 n,表示项链长度. 第二行 n 个正整数 ai?,表示项链中第 iii 个贝壳的种类. 第三行一个整数 m,表示 H

BZOJ 1878: [SDOI2009]HH的项链( BIT )

离线处理 , 记下询问的左右端点并排序 , 然后可以利用树状数组 , 保证查询区间时每种颜色只计算一次 ------------------------------------------------------------------------------------------------ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define

[bzoj1878] [SDOI2009]HH的项链(树状数组+离线)

1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3210  Solved: 1619[Submit][Status][Discuss] Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的

「树状数组」[SDOI2009]HH的项链

[SDOI2009]HH的项链 原题链接 [SDOI2009]HH的项链 题目大意 给你 \(n\) 个数,再给你 \(q\) 次询问,每次询问给你 \(l, r\) ,问你 \(l, r\) 中有多少个不同的数 题目题解 分析这道题我们发现,对于一个 \([L_1, R_1]\) 存在另一个 \([L_2, R_1]\) 且 \(L_2\) 严格大于 \(L_1\),那么就一定存在第一个区间不同的数 大于等于 第二个区间的不同的数,这里很显然有一种等于的情况,什么情况等于?在\([L_2,R_

BZOJ 1878 [SDOI2009]HH的项链 (主席树 或 莫队算法)

题目链接  HH的项链 这道题可以直接上主席树的模板 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 5e4 + 10; const int M = 3e6 + 10