题目链接:点击打开链接
线段树离散化区间染色。
数据范围是int最大值,肯定要离散化,离散化时要注意加点。
举几个个例子:
1. 输入 1,2,4,5,如果离散成1,2,3,4那么本来最长区间是1到2,离散后就变成1到4了,这就要在2和4之间加点。
2. 输入 1 5 w,3 5 b,最长区间应是1到2,但是不加点的话没有点表示2,得不到1到2这个结果,需要添加点2
3. 输入 1 5 w,1 3 b,最长区间是4到5,同理需要加4这个点
综上,离散化的步骤是先对原数组排序(代码中用tmp表示),然后加上这两句:
if(tmp[i]-tmp[i-1]>1) Hash[++k]=tmp[i]-1;
if(tmp[i]-tmp[i-1]>2) Hash[++k]=tmp[i-1]+1;
另外统计结果的方法是遍历叶子节点,找最长区间,所以此线段树不需要pushup,只需要能把改变传到下面的pushdown即可。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#include <algorithm>
using namespace std;
#define MAX 30000
int Hash[MAX*2];
int res[MAX<<2];
int col[MAX<<2];
int ans[MAX*2];
struct seg{
int s,t;
int c;
}p[MAX];
void pushdown(int rt){
if(col[rt]){
col[rt<<1]=col[rt<<1|1]=col[rt];
res[rt<<1]=res[rt<<1|1]=col[rt];
col[rt]=0;
}
}
void build(int l,int r,int rt){
col[rt]=0;
res[rt]=2;
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&R>=r){
res[rt]=c;
col[rt]=c;
return ;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
}
void query(int l,int r,int rt){
if(l==r){
ans[l]=res[rt];
return ;
}
int m=(l+r)>>1;
query(lson);
query(rson);
}
void solve(int n){
long long tmp[MAX*2];
int len=0;
for(int i=1;i<=n;i++){
char c[4];
scanf("%d%d%s",&p[i].s,&p[i].t,c);
tmp[++len]=p[i].s;
tmp[++len]=p[i].t;
if(c[0]=='w') p[i].c=1;
else p[i].c=2;
}
sort(tmp+1,tmp+len+1);
int k=0;
Hash[++k]=tmp[1];
for(int i=2;i<=len;i++){
Hash[++k]=tmp[i];
if(tmp[i]-tmp[i-1]>1) Hash[++k]=tmp[i]-1;
if(tmp[i]-tmp[i-1]>2) Hash[++k]=tmp[i-1]+1;
}
sort(Hash+1,Hash+k+1);
len=unique(Hash+1,Hash+k+1)-Hash-1;
build(1,len,1);
for(int i=1;i<=n;i++){
int s=lower_bound(Hash+1,Hash+len+1,p[i].s)-Hash;
int t=lower_bound(Hash+1,Hash+len+1,p[i].t)-Hash;
if(s>t) continue;
update(s,t,p[i].c,1,len,1);
}
query(1,len,1);
int answer=-1;
int l=0,r=0;
bool flag=0;
for(int i=1;i<=len;i++){
int j=i;
if(ans[i]==1){
flag=1;
int tmp=0;
while(j<len&&ans[j+1]==1){
j++;
}
tmp=Hash[j]-Hash[i];
if(tmp>answer){
answer=tmp;
l=Hash[i];
r=Hash[j];
}
}
i=j;
}
if(!flag) printf("0\n");
else printf("%d %d\n",l,r);
}
int main(){
int n;
while(~scanf("%d",&n)){
solve(n);
}
return 0;
}
本文介绍了一种使用线段树进行离散化区间染色的方法,重点讲解了离散化过程中如何正确地添加额外的点来确保区间长度的准确性,并提供了一个完整的实现代码示例。
1163

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



