决定将这个再写一遍,这是以前的代码。
/*
Pro: poj-2528
Sol:
date:2012/07/03
*/
#include<iostream>
#include <cstring>
#include <cstdio>
#include<algorithm>
//这个define还不能用加的,这么低级啊。。。
#define N 10010
using namespace std;
int Case,n,dis[10000100],s[N],e[N],cnt,tp[2 * N],all,tag[N];
struct you{
int s,e,col;
you():s(0),e(0),col(0){};//
}lt[N * 8];
void discrete(){
all = 0;
for(int i = 0; i < n; i ++){
if(!dis[s[i]])
{tp[all++] = s[i]; dis[s[i]] = 1;}//去重!!!
if(!dis[e[i]]){
tp[all ++] = e[i]; dis[e[i]] = 1;
}
}
sort(tp,tp + all);
for(int i = 0; i < all; i ++){//把排好序的端点依次映射到1,2,...,all
dis[tp[i]] = i + 1;//离散化肿么用???,颜色从1开始
}
}
void creat(int sp,int ep,int p){//如何调用creat???
lt[p].s = sp;//
lt[p].e = ep;
if(sp == ep) return;
int mid = (sp + ep) >> 1;
creat(sp,mid, 2 * p);
creat(mid + 1, ep, 2 * p + 1); return ;
}
void insert(int a,int b, int p, int color){//p 是干什么的?
//[a,b]与[s,e]完全无交集
//说明[a,b]不被[s,e]所在的子树包含,无需向下搜索
if(b < lt[p].s || a > lt[p].e) return ;
//完全覆盖, [a,b]完全覆盖[s,e]
if(a <= lt[p].s && b >= lt[p].e) {
lt[p].col = color; return ;
//[s,e]染单色,暂时无需对[s,e]的子树操作(这是由线段树的搜索机制决定的)
}
//[a,b]颜色部分覆盖[s,e],本身无色或单色,需对子树操作
if(lt[p].col >= 0){//单色或者无色 0 --- 无色 1 ---- 单色 -1 ----多种颜色
lt[p * 2].col = lt[p * 2 + 1].col = lt[p].col; //给孩子保存
lt[p].col = -1; //多色
}
//本身多色,从左子树和右子树开始搜
insert(a,b,p * 2,color); //觉得可以改进
insert(a,b,p * 2 + 1, color);
return;
}
void dfs(int p){//这里p又是干什么的---p是一个下标
//无色
if(lt[p].col == 0) return;
//单色
if(lt[p].col > 0){
if(!tag[lt[p].col]){//数颜色
tag[lt[p].col] = 1;
cnt ++;
}
return ; //单色数了颜色之后就返回
}
//多色
dfs(p * 2); dfs(p * 2 + 1); return ;
}
void solution(){
cnt = 0; memset(tag,0,sizeof(tag));
discrete();
creat(1,all,1);//从1开始建树
for(int i = 0; i < n; i ++){//插入
insert(dis[s[i]],dis[e[i]], 1, i + 1); //离散化的使用
}
dfs(1);//数颜色
printf("%d\n",cnt);
return ;
}
int main(){
cin >> Case;
while(Case --){
cin >> n; memset(dis,0,sizeof(dis));
for(int i = 0 ; i < n; i ++){
scanf("%d%d",s + i, e + i);
}
solution();
}
return 0;
}
最新代码:(-1表示这个区间多色)
/*
Pro: poj-2528
Sol:
date:2012/09/15
*/
#include<iostream>
#include <cstring>
#include <cstdio>
#include<algorithm>
#define lson l,m, rt << 1
#define rson m + 1, r, rt << 1|1
#define havem int m = (l + r) >> 1
//这个define还不能用加的,这么低级啊。。。
const int maxn = 10010;
using namespace std;
int T, col[maxn << 4],n,li[maxn],ri[maxn],X[maxn * 3],cnt;
bool hash[maxn << 1];
void push_dn(int rt){
if(col[rt] != -1){
col[rt << 1] = col[rt << 1 | 1] = col[rt];
col[rt] = -1;
}
}
void push_up(int rt){
if(col[rt << 1] != col[rt << 1 | 1]) col[rt] = -1;
}
void update(int L, int R, int cc,int l, int r, int rt){
if(L <= l && r <= R){
col[rt] = cc; return ;
}havem;
push_dn(rt);
if(L <= m) update(L,R,cc,lson);
if(R > m) update(L,R,cc,rson);
// push_up(rt);
}
void query(int L, int R, int l , int r, int rt){
if(L <= l && r <= R){
if(col[rt] != -1){
if(!hash[col[rt]]) cnt ++;
hash[col[rt]] = true;
return ;
}
}havem;
if(l == r) return ;
push_dn(rt);
if(L <= m) query(L,R,lson);
if(R > m) query(L,R,rson);
}
int main(){
scanf("%d",&T);
while(T --){
scanf("%d",&n);
int xsub = 0;
for(int i = 0; i < n; i ++){
scanf("%d%d",&li[i],&ri[i]);
X[xsub ++] = li[i];
X[xsub ++] = ri[i];
}
sort(X, X + xsub);//下标这里得特别注意
int m = 1;
for(int i = 1; i < xsub; i ++){
if(X[i] != X[i - 1]) X[m ++] = X[i];
}
xsub = m;
for(int i = 1; i < xsub; i ++){
if(X[i] != X[i - 1] + 1) X[m ++] = X[i - 1] + 1;
}
sort(X,X + m);
memset(col, - 1, sizeof(col)); //-1 即是开始,又是表示多色
for(int i = 0; i < n; i ++){
int l = lower_bound(X,X + m,li[i]) - X + 1;
int r = lower_bound(X,X + m,ri[i]) - X + 1;
update(l,r,i,1,m,1);
}
memset(hash,0,sizeof(hash));
cnt = 0;
query(1,m,1,m,1);
// int cnt = 0;
// for(int i = 0; i < n; i ++)//这里必须是n,m不一定比n大
// if(hash[i])
// cnt ++;
printf("%d\n",cnt);
}
return 0;
}
本文详细解析了POJ-2528题目,通过离散化和线段树实现区间染色问题,提供了两种不同的代码实现方案。
744

被折叠的 条评论
为什么被折叠?



