ZOJ - 1610 Count the Colors(線段樹區間更新)

Count the Colors

題意:每次對區間染色,注意不染端點,然後問最後每種顏色有多少段。
題解:用線段樹維護每個區間的顏色信息,然後因爲不染端點,因此如果染040\rightarrow4,只會染44個區間那麼我們將左端點加一即可。其它就是經典線段樹lazylazy標記下放了。

代碼

#include<bits/stdc++.h>

#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

using namespace std;
//0 1 2 3 4
//|4|4|4|4|
//|1|1|1|4|
//|1|1|1|2|
//|2|2|1|2|
//|3|3|1|2|
const int N = 8010;
int tr[N << 2], ans[N],color[N];

void pushdown(int rt)
{
	if(tr[rt] != -1) {
		tr[rt << 1] = tr[rt];
		tr[rt << 1 | 1] = tr[rt];
		tr[rt] = -1;
	}	
}

void update(int rt,int l,int r,int x,int y,int z)
{
	if(x <= l && r <= y) {
		tr[rt] = z;
		return;
	}
	int mid = l + r >> 1;
	pushdown(rt);
	if(x <= mid) update(rt << 1, l, mid, x, y, z);
	if(y > mid) update(rt << 1 | 1, mid + 1, r, x, y, z);
}

void query(int rt,int l,int r,int x,int y)
{
	if(x <= l && r <= y) {
		if(tr[rt] != -1) {
			for(int i = l; i <= r; ++i) {
				color[i] = tr[rt];
			}
			return;
		}
	}
	if(l == r) return;
	int mid = l + r >> 1;
	if(x <= mid)
		query(rt << 1, l, mid, x, y);
	if(y > mid)
		query(rt << 1 | 1, mid + 1, r, x, y);
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	int n,x,y,z;
	while(cin >> n) {
		memset(tr, -1, sizeof tr);
		memset(ans, 0, sizeof ans);
		memset(color,-1,sizeof color);
		while(n--) {
			cin >> x >> y >> z;
			if(x >= y) continue;
			update(1,1,N,x + 1,y,z);
		}
		query(1,1,N,1,N);
		for(int i = 1; i < N; ++i) {
			if(color[i] == -1) continue;
			int c = color[i];
			ans[c]++;
			for(; i < N && color[i] == c; ++i);
			i--;
		}
		for(int i = 0; i < N; ++i) {
			if(ans[i]) cout << i << ' ' << ans[i] << endl;
		}
		cout << endl;
	}
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章