POJ 2528 Mayor's posters (线段树)
题目链接:http://poj.org/problem?id=2528
题目大意:有一个很上的面板, 往上面贴海报, 问最后最多有多少个海报没有被完全覆盖
解题思路:将贴海报倒着想, 对于每一张海报只需要判断他要贴的位置是否已经全部被之前的海报覆盖就可以了, 如果没有被覆盖那么这个海报最后是没有被完全覆盖的, 如果被覆盖了, 那么最后是被完全覆盖的。标准的线段树题目.
代码如下:
#include<stdio.h> #include<vector> #include<map> #include<algorithm> using namespace std; const int N = 10003; pair<int, int>edge[N]; vector<int> vec; map<int, int> mp; struct SegmentTree { int l, r; bool mk; bool lazy; }; SegmentTree tree[N << 5]; void build(int l, int r, int k) { tree[k].l = l, tree[k].r = r, tree[k].mk = false, tree[k].lazy = false; if(l== r) return; int mid = (l + r) >> 1; build(l, mid, k<<1); build(mid+1, r, k<<1|1); } bool query(int l, int r, int k) { if(tree[k].mk) return true; if(tree[k].l >= l && tree[k].r <= r) return tree[k].mk; bool a = true, b = true; if(tree[k<<1].r >= l) a = query(l, r, k<<1); if(tree[k<<1|1].l <= r) b = query(l, r, k<<1|1); return (a && b); } void updata(int l, int r, int k) { if(tree[k].l >= l && tree[k].r <= r) { tree[k].mk = true; tree[k].lazy = true; return; } if(tree[k].lazy) { tree[k<<1].lazy = tree[k<<1|1].lazy = true; tree[k].lazy = false; tree[k<<1].mk = tree[k<<1|1].mk = true; } if(tree[k<<1].r >= l) updata(l, r, k<<1); if(tree[k<<1|1].l <= r) updata(l, r, k<<1|1); tree[k].mk = (tree[k<<1].mk && tree[k<<1|1].mk); } void solve() { int n; scanf("%d", &n); vec.clear(); for(int i=0; i<n; ++ i) { scanf("%d%d", &edge[i].first, &edge[i].second); vec.push_back(edge[i].first); vec.push_back(edge[i].second); } sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end()); mp.clear(); int s = 1; for(int i=0; i<vec.size(); ++ i) { mp[vec[i]] = s; if(i != vec.size() - 1) { if(vec[i+1] == vec[i] + 1) s ++; else s += 2; } } build(1, s, 1); int ans = 0; for(int i=n-1; i>=0; -- i) { int l = mp[edge[i].first], r = mp[edge[i].second]; if(query(l, r, 1) == false) { ans ++; updata(l, r, 1); } } printf("%d\n", ans); } int main() { int t; scanf("%d", &t); while(t --) solve(); return 0; }