Poj 2528 Mayor's posters

题目大意:多位候选人要在墙上贴海报,海报可以相互重叠,问贴完了以后还有多少海报可以看见。

思路:经典的线段树问题,同时需要离散化坐标点。

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>

using namespace std;

const int MAXN = 10000001;//节点数量
const int DISCRETE_MAXN = 10010*2;//离散之后节点数量
const int COLOR_NUM = 20001;//所染颜色数量
const int DEFAULT_COLOR = 0;//默认颜色

struct node{//线段树节点
    int left, right;//区间左右坐标
    int color;
};

node tree[DISCRETE_MAXN*4];
bool visit[COLOR_NUM];
int l, n;


node discreteTree[DISCRETE_MAXN*4];//离散点
bool discreteVisit[MAXN];//标志离散点
int discreteValue[DISCRETE_MAXN*4];//离散值
int discreteNum;//离散量
int resultValue[MAXN];//最终离散值

//离散化
//返回离散化后最大的值
int discrete()
{
    int i = 1;

    scanf("%d", &n);
    for(i = 1 ; i <= n ; i++){
          scanf("%d %d", &discreteTree[i].left, &discreteTree[i].right);

          if(!discreteVisit[discreteTree[i].left]){
              discreteValue[discreteNum++] = discreteTree[i].left;
              discreteVisit[discreteTree[i].left] = true;
          }
          if( !discreteVisit[discreteTree[i].right] ){
              discreteValue[discreteNum++] = discreteTree[i].right;
              discreteVisit[discreteTree[i].right] = true;
          }
    }  
    sort(discreteValue, discreteValue+discreteNum);
    int j = 1;
    for( i = 0 ; i < discreteNum ; i++ ){     //离散化过程
         discreteVisit[discreteValue[i]] = false;
         resultValue[discreteValue[i]] = j++;
    }

    return j-1;
}

//建树
//参数: 区间左边坐标, 区间右边坐标, 节点下标
void build(const int &left, const int &right, const int &nodeNum = 1)
{
    tree[nodeNum].left = left;
    tree[nodeNum].right = right;
    tree[nodeNum].color = DEFAULT_COLOR;

    if (left == right)//终结条件, 区间剩下一个点的时候
        return ;

    int mid = (left + right) >> 1;//求中点

    build(left, mid, 2*nodeNum);//建左子树
    build(mid+1, right, 2*nodeNum+1);//建右子树
}

//建树的初始化函数
void init()
{
    build(1, l);//默认总区间是[1, l]
    tree[1].color = 1;//先给总的区间上一种颜色
}

//往线段树插入数据/修改数据
//参数: 区间左边坐标, 区间右边坐标, 修改的区间颜色, 节点下标
void insert(const int &left, const int &right, const int &color, const int &nodeNum = 1)
{
    if (left == tree[nodeNum].left && right == tree[nodeNum].right){//如果区间刚刚好为要填充的区间, 修改区间的颜色值,终止
        tree[nodeNum].color = color;
        return ;
    }

    if (DEFAULT_COLOR != tree[nodeNum].color){//区间已经染过颜色
        tree[nodeNum*2].color = tree[nodeNum*2+1].color = tree[nodeNum].color;//左右区间记录原来区间的颜色
        tree[nodeNum].color = DEFAULT_COLOR;//区间设置为未染色颜色
    }

    int mid = (tree[nodeNum].left + tree[nodeNum].right) >> 1;//获取区间的中点

    if (right <= mid){//修改区间全在当前的左半部分区间
        insert(left, right, color, nodeNum*2);//去左子树修改颜色值
    }else if (left > mid){//修改区间全在当前的右半部分区间
        insert(left, right, color, nodeNum*2+1);//去右子树修改颜色值
    }else{
        insert(left, mid, color, nodeNum*2);
        insert(mid+1, right, color, nodeNum*2+1);
    }
}

//查询函数
//参数:    查询区间左坐标, 有坐标, 节点下标
//返回:    查询区间里面不同颜色的数量
int query(const int &left, const int &right, const int &nodeNum = 1)
{
    int count = 0;

    if (tree[nodeNum].color != DEFAULT_COLOR)
    {
        if (visit[tree[nodeNum].color] == false)
        {
            count++;
            visit[tree[nodeNum].color] = true;
        }
        return count;
    }

    int mid = (tree[nodeNum].left + tree[nodeNum].right) >> 1;

    if (right <= mid){
        count += query(left, right, nodeNum*2);
    }else if (left > mid){
        count += query(left, right, nodeNum*2 + 1);
    }else
    {
        count += query(left, mid, nodeNum*2);
        count += query(mid+1, right, nodeNum*2 + 1);
    } 
    return count;
}


int main()
{
    int t, color;

    scanf("%d", &t);
    memset(discreteVisit, false, sizeof(discreteVisit));
    while (t--)
    {
        l = 20010;
        init();//线段树初始化
        color = 2;

        discreteNum = 0;
        memset(visit, false, sizeof(visit));
        int maxX = discrete();

        for (int i = 1; i <= n; ++i){
            insert(resultValue[discreteTree[i].left], resultValue[discreteTree[i].right], color++);
        }

        printf("%d\n", query(1, maxX));
    }

    return 0;
}

你可能感兴趣的:(struct,tree,query,insert,Build)