poj 2528 Mayor's posters(线段树)

题目链接:http://poj.org/problem?id=2528

思路分析:线段树处理区间覆盖问题,也可以看做每次给一段区间染不同的颜色,最后求在整段区间上含有的所有颜色种类数;

注意由于区间太大,所以需要离散化;

区间更新:对于线段树的每个结点,标记颜色,初始时没有颜色,标记为0;当更新时,使用延迟标记,需要标记传递到子节点;

区间查询:使用深度优先查询线段树,当某个子节点的颜色不为0时,即停止深度优先搜索,并在map中查询是否已经记录该段区间的颜色;

 

代码如下:

#include <iostream>
#include <algorithm>
using namespace std;

typedef struct { int x, y; }Pos;

const int MAX_N = 10000 + 100;
const int MAX_M = 10000000 + 100;
int hash_val[MAX_M];
int set[20 * MAX_N], arr[8 * MAX_N];
int map[10 * MAX_N];
Pos position[8 * MAX_N];
int ans;

void PushDown(int o)
{
    int lc = 2 * o, rc = 2 * o + 1;
    if (set[o] != 0)
    {
        set[lc] = set[rc] = set[o];
        set[o] = 0;
    }
}

void Updata(int o, int l, int r, int color, int ql, int qr)
{
    if (ql <= l && r <= qr)
        set[o] = color;
    else
    {
        int mid = (l + r) / 2;
        PushDown(o);
        if (ql <= mid)
            Updata(2 * o, l, mid, color, ql, qr);
        if (mid < qr)
            Updata(2 * o + 1, mid + 1, r, color, ql, qr);
    }
}

void Query(int o, int l, int r)
{
    if (set[o] != 0)
    {
        if (map[set[o]] == 0)
        {
            map[set[o]] = 1;
            ans++;
        }
    }
    else if (l < r)
    {
        int mid = (l + r) / 2;

        Query(2 * o, l, mid);
        Query(2 * o + 1, mid + 1, r);
    }
}

int main()
{
    int case_times, num;
    int min_len, max_len;

    scanf("%d", &case_times);
    while (case_times--)
    {
        memset(set, 0, sizeof(set));
        memset(map, 0, sizeof(map));
        memset(hash_val, 0, sizeof(hash_val));

        scanf("%d", &num);
        for (int i = 0; i < num; ++i)
        {
            scanf("%d %d", &arr[2 * i], &arr[2 * i + 1]);
            position[i].x = arr[2 * i];
            position[i].y = arr[2 * i + 1];
        }
        sort(arr, &arr[2 * num]);
        for (int i = 0; i < 2 * num; ++i)
        {
            if (i == 0)
                hash_val[arr[i]] = 1;
            else if (arr[i] == arr[i - 1])
                hash_val[arr[i]] = hash_val[arr[i - 1]];
            else if (arr[i] == arr[i - 1] + 1)
                hash_val[arr[i]] = hash_val[arr[i - 1]] + 1;
            else
                hash_val[arr[i]] = hash_val[arr[i - 1]] + 2;
        }
        min_len = 1;
        max_len = hash_val[arr[2 * num - 1]];
        for (int i = 0; i < num; ++i)
        {
            int ql = hash_val[position[i].x];
            int qr = hash_val[position[i].y];
            Updata(1, min_len, max_len, i + 1, ql, qr);
        }
        ans = 0;
        Query(1, min_len, max_len);
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(post)