POJ 2528 Mayor's posters(线段树+离散化)
来源:互联网 发布:易游网络验证山寨 编辑:程序博客网 时间:2024/05/29 16:37
题目大意:
将一些海报贴在一排的瓷砖上,这些海报的高度是一样的,且在贴的过程总保持所有海报的高度一致,海报是完整的贴在每块瓷砖上的(也就是说,如果海报覆盖了一块瓷砖,那就是完全覆盖该瓷砖),先给出张贴海报覆盖瓷砖的左边瓷砖的编号和右边瓷砖的编号(给出的顺序是按照张贴的顺序给出的)。求所有海报都张贴完之后有多少海报是完全或者部分可见的。
解题思路:
最后张贴的那张海报一定是完全可见的。本题用线段是来做,每块瓷砖对用一个线段树中的叶子节点,表示节点的结构体为:
struct CNode { //线段树中每个结点的结构体定义 int L, R; //结点所表示的区间[L,R] bool isCover; //结点表示的区间是否被海报完全覆盖 CNode *pLeft, *pRight; //左子树指针和右子树指针};
还要注意的是:因为瓷砖的个数非常多(10,000,000),而海报的个数少(10,000),如果用线段树把瓷砖完整的区间表示出来(即:0~10,000,000),则在程序运行中会出现MLE。所以本题还要对海报的端点进行离散化,海报的个数为N,则顶点的个数最多有(2*N 10^4级别的),用线段树完全可以表示该区间(0~20,000)。
在遍历离散化后的海报区间时,必须按照从最近张贴的海报开始遍历,否则张贴的海报会影响已经张贴的海报的可见情况。
代码:
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#define M 1000000using namespace std;struct Poster { //海报的左边和右边 int L, R;};Poster poster[10100]; //海报的数量struct CNode { //线段树中每个结点的结构体定义 int L, R; //结点所表示的区间[L,R] bool isCover; //结点表示的区间是否被海报完全覆盖 CNode *pLeft, *pRight; //左子树指针和右子树指针};CNode Tree[1000000]; //Tree[i]线段树的第i个结点int x[20200], hash[10000010]; //x[]保存所有的海报的端点值,并按从小到大的循序排序并合并重复值 //hash[]是海报的端点值对应的哈希值int nNodeCount = 0;int Mid(CNode *pNode) { return (pNode->R + pNode->L) / 2;}void BuildTree(CNode *pRoot, int l, int r) { //建树,确定每个结点的L和R值、左右子树的指针, //初始化isCover为false:结点表示的 //区间没有被海报完全覆盖, pRoot->L = l; pRoot->R = r; pRoot->isCover = false; if(l == r) return ; nNodeCount ++; pRoot->pLeft = Tree + nNodeCount; nNodeCount ++; pRoot->pRight = Tree + nNodeCount; BuildTree(pRoot->pLeft, l, Mid(pRoot)); BuildTree(pRoot->pRight, Mid(pRoot)+1, r);}bool Query(CNode *pRoot, int l, int r) { //每贴一张海报,检查海报的[l,r]是否已经被其他海报完全覆盖 if(pRoot->isCover) return false; //如果pRoot结点表示的区间(肯定覆盖了[l,r]区间)被完全覆盖, //直接返回false if(pRoot->L == l && pRoot->R == r) { //能够走到这段代码,说明[l,r]没有被完全覆盖 //如果海报的[l,r]和结点pRoot表示的区间想吻合,更新该结点 //的isCover的值。表示该顶点表示的区间被该海报完全覆盖 pRoot->isCover = true; return true; } //[l,r]真包含于[pRoot->L, pRoot->R] bool Result; if(r <= Mid(pRoot)) { //线段树常用语法,如果(l,r)在pRoot的左子树,则进入左子树 Result = Query(pRoot->pLeft, l, r); } else if(l > Mid(pRoot)) { //进入右子树 Result = Query(pRoot->pRight, l, r); } else { //部分进入左子树,部分进入右子树 bool b1 = Query(pRoot->pLeft, l, Mid(pRoot)); bool b2 = Query(pRoot->pRight, Mid(pRoot)+1, r); Result = b1 || b2; //Result = Query(pRoot->pLeft, l, Mid(pRoot)) || Query(pRoot->pRight, Mid(pRoot)+1, r); //注释的部分是错误的,如果第一个Query()为true,后面的Query()函数就不会执行 } if(pRoot->pLeft->isCover && pRoot->pRight->isCover) pRoot->isCover = true; return Result;}int main() { int t, nCount; //nCount=所有海报端点值(l和r)的个数 scanf("%d", &t); while(t--) { int n; scanf("%d", &n); nCount = 0; for(int i=0; i<n; i++) { scanf("%d%d", &poster[i].L, &poster[i].R); x[nCount++] = poster[i].L; x[nCount++] = poster[i].R; } sort(x, x+nCount); nCount = unique(x, x+nCount) - x; //合并x[]中重复的元素 int nIntervalNo = 0; for(int i=0; i<nCount; i++) { //将每一个x[i]离散化,因为x[i]的值很大(10^7),如果用x[i]的值表示的 //区间建树BuildTree(Tree, 0, max(x[i])),则程序在运行过程中会MLE hash[x[i]] = nIntervalNo; if(i < nCount - 1) { if(x[i+1] == x[i]+1) nIntervalNo ++; else nIntervalNo += 2; //相邻x[i]和x[i+1]的值相差超过1,则忽略两个数过大的差值,将其差值 //认为是2,形象一点:如果几张海报都覆盖了连续的几块瓷砖,则任务他们 //值覆盖了两个瓷砖,即把该连续的几块瓷砖认为两块瓷砖。 } } nNodeCount = 0; BuildTree(Tree, 0, nIntervalNo); //建树 int ans = 0; for(int i=n-1; i>=0; i--) { //从最近张贴的海报遍历所有的海报。从n-1~0遍历海报可以确保对于已经 //遍历过的海报不会受到还没有遍历过的海报的影响 if(Query(Tree, hash[poster[i].L], hash[poster[i].R])) ans ++; } printf("%d\n", ans); } return 0;}
0 0
- 离散化+线段树 POJ 2528 (Mayor's posters)
- POJ 2528 Mayor's posters(离散化+线段树)
- poj 2528 Mayor's posters 离散化 线段树
- POJ 2528 Mayor's posters 线段树+离散化
- poj 2528 Mayor's posters 线段树+离散化
- POJ 2528 Mayor's posters (线段树+离散化)
- POJ 2528 Mayor's posters(离散化+线段树)
- POJ 2528 Mayor's posters 线段树+离散化
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters (线段树+离散化)
- poj 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters 线段树+离散化
- poj - 2528 - Mayor's posters 线段树+离散化
- poj 2528 Mayor's posters 线段树+离散化
- poj 2528 Mayor's posters(离散化+线段树)
- POJ 2528 Mayor's posters (线段树+离散化)
- poj 2528 Mayor's posters(离散化+线段树)
- POJ 2528 Mayor's posters 离散化线段树
- POJ2304 Combination Lock
- 策略模式
- 理解RESTful架构
- lua gc(二)
- V4L2文档翻译(二)
- POJ 2528 Mayor's posters(线段树+离散化)
- vibe 代码学习
- spring mvc 时间绑定
- ViewFilpper ViewSwitcher
- RESTful API 设计指南
- V4L2文档翻译(三)
- Princeton Algorithms: Part 1 [week 5: Geometric Searching Applications of BSTs]
- URL POST提交为没有变量名的json串格式
- SQL Server--> 问题处理 --> sql server 错误: 18456,严重性: 14,状态: 38