POJ 2528 Mayor's posters 區間染色問題
阿新 • • 發佈:2018-12-09
題目意思
每個案例一個數字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);
}
}