标签:
题目链接:http://poj.org/problem?id=2528
题意:有n张海报要贴,每张需要用的区间为L到R,后面的可以贴在之前的上面,就是吧之前的挡住,求最后我们能看到几张海报;
我们可以倒着处理,因为最后贴的我们是能看到的;如果区间被贴过了result不加,没有贴过就+1并标记一下;
由于数据范围太大所以用线段树
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> using namespace std; #define N 10100 #define Lson r<<1 #define Rson r<<1|1 struct Post { int L,R; }p[N]; struct SegTree { int L, R, isCover; int Mid() { return (L+R)/2; } }a[N*16]; int Hash[4*N]; void Up(int r) { if(a[r].L!=a[r].R) if(a[Lson].isCover==1 && a[Rson].isCover==1)//向上更新,如果左右子树都被覆盖,那么他也会被覆盖 a[r].isCover = 1; } void BuildSegTree(int r, int L, int R) { a[r].isCover = 0; a[r].L = L; a[r].R = R; if(L == R) return ; BuildSegTree(Lson, L, a[r].Mid()); BuildSegTree(Rson, a[r].Mid()+1, R); } int judge(int r, int L, int R) { if(a[r].isCover==1) return 0;//被覆盖返回0; if(a[r].R == R && a[r].L == L) { a[r].isCover = 1; return 1; } int ans; if(L>a[r].Mid()) ans = judge(Rson, L, R); else if(R<=a[r].Mid()) ans = judge(Lson, L, R); else { int ans1 = judge(Lson, L, a[r].Mid()); int ans2 = judge(Rson, a[r].Mid()+1, R); ans = ans1 | ans2;//只要有一个没被覆盖就说明能贴; } Up(r); return ans; } int main() { int T, n, k; scanf("%d", &T); while(T--) { scanf("%d", &n); k=0; for(int i=1; i<=n; i++) { scanf("%d%d", &p[i].L, &p[i].R); Hash[k++]=p[i].L-1;//防止出现离散化后原本不相邻的数变成相邻的了 Hash[k++]=p[i].L; Hash[k++]=p[i].R+1; Hash[k++]=p[i].R; } sort(Hash, Hash+k); int len = unique(Hash, Hash+k) - Hash; BuildSegTree(1, 1, len); int result = 0; for(int i=n; i>0; i--) { int L = lower_bound(Hash, Hash+len, p[i].L) - Hash; int R = lower_bound(Hash, Hash+len, p[i].R) - Hash; int ans=judge(1, L, R); if(ans == 1) result++; } printf("%d\n", result); } return 0; }
Mayor's posters---poj2528线段树、离散化
标签:
原文地址:http://www.cnblogs.com/zhengguiping--9876/p/4691126.html