• bzoj1878 [SDOI2009]HH的项链


    1878: [SDOI2009]HH的项链

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 3199  Solved: 1611
    [Submit][Status][Discuss]

    Description

    HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。

    Input

    第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

    Output

    M行,每行一个整数,依次表示询问对应的答案。

    Sample Input

    6
    1 2 3 4 3 5
    3
    1 2
    3 5
    2 6

    Sample Output

    2
    2
    4

    HINT


    对于20%的数据,N ≤ 100,M ≤ 1000;
    对于40%的数据,N ≤ 3000,M ≤ 200000;
    对于100%的数据,N ≤ 50000,M ≤ 200000。

    Source

    Day2

    分析:看到区间求数量,似乎可以用线段树解决,但是颜色的数量不能直接相加,故用线段树处理有些麻烦,如果不用线段树解决的话所有询问最好都是有序的,因此先按照左端点排序.

           如果我们询问区间[x,y],那么如果有一个颜色重复出现了多次,那么只需要计算一次即可,那么就要把区间内所有重复的颜色看成一个,具体是哪一个呢?因为要选一个特殊的点,那么一定要选一个特殊的位置,那么我们选择从左边出现的第一个,记为i,如果i的左边还有与i相同的颜色,那么一定在区间[x,y]之外,因为要求个数,那么就把区间[x,y]左边的颜色的下一个相同颜色的位置+1即可,因为是按照左端点排序的,所以不会重复计算,因为涉及到大量的区间计算,所以用到树状数组和前缀和,说的比较抽象,看一组数据:1 2 1 3,树状数组为:0 0 0 0,首先发现了第一个1,树状数组变成1 0 0 0,然后发现了2,变成了1 1 0 0,然后发现了1,变成了0 1 1 0,然后发现了3,变成0 1 1 1,对于一个询问[2,3],那么答案就是sum(3) - sum(2 - 1).那如果是求[1,1]呢?现在的答案是0!怎么办?其实根据之前的叙述,每次只需要考虑区间[x,y]左边的颜色即可,不好描述,如果不能理解请手动模拟几组数据就能找到规律了.

    推荐一篇学习树状数组的博客:http://blog.csdn.net/int64ago/article/details/7429868

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 50010, maxm = 200010, maxk = 1000010;
    
    struct node
    {
        int x, y, id;
    }a[maxm];
    
    int n,f[maxn],nextt[maxk],head[maxk],tempmax,s[maxn],m,ans[maxm];
    
    bool cmp1(node p, node q)
    {
        return p.x < q.x;
        if (p.x == q.x)
            return p.y < q.y;
    }
    
    void add(int x, int y)
    {
        for (;x <= n; x += x&-x)
            s[x] += y;
    }
    
    int query(int x)
    {
        int temp = 0;
        for (;x;x -= x&-x)
            temp += s[x];
        return temp;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &f[i]);
        for (int i = n; i >= 1; i--)
        {
            nextt[i] = head[f[i]];
            head[f[i]] = i;
            tempmax = max(tempmax, f[i]);
        }
        scanf("%d", &m);
        for (int i = 1; i <= m; i++)
        {
            scanf("%d%d", &a[i].x, &a[i].y);
            a[i].id = i;
        }
        sort(a + 1, a + 1 + m, cmp1);
        for (int i = 1; i <= tempmax; i++)
            if (head[i])
                add(head[i], 1);
        int cursor = 1;
        for (int i = 1; i <= m; i++)
        {
            while (cursor < a[i].x)
            {
                if (nextt[cursor])
                    add(nextt[cursor], 1);
                cursor++;
            }
            ans[a[i].id] = query(a[i].y) - query(a[i].x - 1);
        }
        for (int i = 1; i <= m; i++)
            printf("%d
    ", ans[i]);
    
        return 0;
    }
  • 相关阅读:
    Python学习札记(十五) 高级特性1 切片
    LeetCode Longest Substring Without Repeating Characters
    Python学习札记(十四) Function4 递归函数 & Hanoi Tower
    single number和变体
    tusen 刷题
    实验室网站
    leetcode 76. Minimum Window Substring
    leetcode 4. Median of Two Sorted Arrays
    leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surrounded Regions 、434. Number of Islands II(lintcode) 并查集 、178. Graph Valid Tree(lintcode)
    刷题注意事项
  • 原文地址:https://www.cnblogs.com/zbtrs/p/5858030.html
Copyright © 2020-2023  润新知