POJ-2528 线段树 区间修改

一、内容

POJ-2528 线段树 区间修改_第1张图片

二、思路

  • 就是求一共有多少张海报自己能够看到,给每张海报附上一个颜色,最后求自己能够看到多少种颜色。

  • 对数据进行离散化,由于是对一段进行连续化,故当2个点之间的差值大于1时,应该在中间再添加一个点。
    比如 【1, 10】 【1,4】【5, 10】 离散化后是【1,4】【1,2】【3, 4】
    然而 【1, 10】 【1,4】【6, 10】离散化后也是【1,4】【1,2】【3, 4】,然而这种情况看到的数量应该是3
    所以我们应该在4 和 6 中间添加一个点5,这样进行区间修改的时候就不会出错。

  • color[]初始值为-1 代表没有颜色或者有多种颜色, 我们每次跟新的时候都更新到一段区间就行了,然后每次进行pushdown();将一段区间分成2段区间,因为要覆盖的区间可能是子区间的一段。
    -最后query() 查询一共有多少种颜色就行了, 用一个vis记录已经看到的颜色

三、代码

#include 
#include 
#include 
#include  
using namespace std;
const int maxn = 2e4 + 5;


//color用来保存一段区间的颜色,vis用来统计颜色  lId保存海报的左端点    id保存离散化后的编号 
int color[maxn << 4], vis[maxn << 4], lId[maxn], rId[maxn], id[maxn << 2];  
int t, n, cnt, ans; 
void pushdown(int id) {
	if (color[id] == -1) return;
	//对修改过的区间进行下放 
	color[id << 1] = color[id << 1 | 1] = color[id];
	color[id]  = -1;
}

void update(int id, int l, int r, int x, int y, int v) {
	if (x <= l && r <= y) {
		//对区间进行修改 
		color[id] = v;
		return;
	}
	 pushdown(id);
	int mid = (l + r) >> 1;
	if (x <= mid) {
		update(id << 1, l , mid, x, y, v); 
	}		 
	if (y > mid) {
		update(id << 1 | 1, mid + 1, r, x, y, v);
	}
	//这种还不用pushup 
} 
void  query(int id, int l, int r) {
	if (color[id] != -1) {
		//记录一种color 
		if (!vis[color[id]]) {
			ans++;
			vis[color[id]] = 1;
		}
		return;
	}
	if (l == r) return; 
	int mid = (l + r) >> 1;
	query(id << 1, l, mid);
	query(id << 1 | 1, mid + 1,r);
}


int main() {
	scanf("%d", &t);
	while (t--) {
		cnt = 0;
		ans = 0;
		memset(color, -1, sizeof(color));
		memset(vis, 0, sizeof(vis));
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) {
			scanf("%d%d", lId + i, rId + i);
			id[++cnt] = lId[i];
			id[++cnt] = rId[i];
		} 
		sort(id + 1, id + cnt + 1);
		int t = unique(id + 1, id + cnt + 1) - id - 1;
		int m = t;
		for (int i = 2; i <= t; i++) {
			if (id[i] - id[i - 1] > 1) {
				//成段的离散化若差值大于1 中间还应该添加一个点 
				id[++m] = id[i  - 1] + 1;
			}
		}
		cnt = m;
		sort(id + 1, id + cnt + 1);
		for (int i = 1; i <= n; i++) {
			int x = lower_bound(id + 1, id + cnt + 1, lId[i]) - id;
			int y = lower_bound(id + 1, id + cnt + 1, rId[i]) - id;
			update(1, 1, cnt, x, y, i);
		}
		query(1, 1, cnt); 
		printf("%d\n", ans);
	}
	
	
	return 0;
} 

你可能感兴趣的:(线段树,POJ)