1. 程式人生 > >POJ 2528 Mayor's posters 區間染色問題

POJ 2528 Mayor's posters 區間染色問題

題目意思

每個案例一個數字n,接下來n行表示張貼海報的起點與終點,求有多少海報沒有被完全遮住,經典區間染色問題。本題資料量比較大,所以需要將起點和終點離散化處理。

Sample Input 1 5 1 4 2 6 8 10 3 4 7 10 Sample Output 4

解題思路

針對每一次update,若當前區間在詢問區間內,直接更新當前區間mark並return,若無交集,直接retrun,反之迭代至下一次。 查詢時,若查到當前區間mark不為0時,標記該mark並return,最後數一數book中標記個數即為所求答案。

AC程式碼

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
using namespace std;
ll ql, qr, val;
int book[200005];
int a[200005];
struct node
{
    int l;
    int r;
    ll mark;
}que[200005
]; struct Node { int s; int e; }dot[200005]; void push_down(int k) { if (que[k].mark) { que[k << 1].mark = que[k].mark; que[k << 1 | 1].mark = que[k].mark; que[k].mark = 0; } } void build(int left, int right,int k) { que[k].l = left; que[k].r = right; que[k].mark = 0
; if (left == right) return; int mid = (left + right) >> 1; build(lson); build(rson); } void update(int left, int right, int k) { if (ql <= left && right <= qr) { que[k].mark = val; return; } if (right < ql || qr < left) return; push_down(k); int mid = (left + right) >> 1; update(lson); update(rson); } void query(int left, int right, int k) { if (que[k].mark) { book[que[k].mark] = 1; return; } if (left == right) return; int mid = (left + right) >> 1; query(lson); query(rson); } int main() { int t; scanf("%d", &t); while (t--) { int x = 0, ans = 0; memset(book, 0, sizeof book); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d%d", &dot[i].s, &dot[i].e); a[x++] = dot[i].s; a[x++] = dot[i].e; } //離散化 sort(a, a + x); int all = unique(a, a + x) - a; build(1, all, 1); for (int i = 0; i < n; i++) { //離散化 dot[i].s = lower_bound(a, a + all, dot[i].s) - a + 1; dot[i].e = lower_bound(a, a + all, dot[i].e) - a + 1; ql = dot[i].s; qr = dot[i].e; val = i + 1; update(1, all, 1); } ql = 1; qr = all; query(1, all, 1); for (int i = 1; i < 200005; i++) if (book[i]) ans++; printf("%d\n", ans); } }