zoj zju 3324 线段树 离散化

当线段树调试不出来的时候,请画一棵树,设个断点,照着你的树走,走完你就AC了

poj 2528的离散化方法如出一辙,如果两个相邻数的大小大于1 ,在中间插入一个任意的数

线段树更新的过程类似于求周长并,需要判断左右边界是否是一样的高度(左儿子的右边界与右儿子的左边界)

我是左闭右闭的线段树,所以开始的时候要把n-1加进来(这里错了好几次,一直加了n) ,另外0也要加进来。

举个例子:区间长度为10 现在总共记录了1 3 5 7

所以要先把0 9 加进来

离散化后是0 1 2 3 4 5 6 7 8 9

下面这个函数其实是把两个功能结合在一起了

View Code
void pushup(int rt,int l,int r){
if(col[rt]){
sum[rt]=0;
lbd[rt]=rbd[rt]=1;
return ;
}
if(l==r){
lbd[rt]=rbd[rt]=0;
sum[rt]=1;
return;
}
lbd[rt]=lbd[LL];
rbd[rt]=rbd[RR];
sum[rt]=sum[LL]+sum[RR]-(!rbd[LL]&&!lbd[RR]);
}


线段树的四个域:

col[maxn<<2]:当前区间被覆盖次数

sum[maxn<<2]:管辖区间内总的在原位(没有被下压)连续区间的段数
int lbd[maxn<<2]:左边界的高度

rbd[maxn<<2]:右边界的高度,初始时为0;

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL rt<<1
#define RR rt<<1|1
#define lson l,m,LL
#define rson m+1,r,RR
const int maxn = 44444;
int col[maxn<<2],sum[maxn<<2];
int lbd[maxn<<2],rbd[maxn<<2];
struct node{
char op[5];
int l,r;
}q[22222];
int x[maxn];
void pushup(int rt,int l,int r){
if(col[rt]){
sum[rt]=0;
lbd[rt]=rbd[rt]=1;
return ;
}
if(l==r){
lbd[rt]=rbd[rt]=0;
sum[rt]=1;
return;
}
lbd[rt]=lbd[LL];
rbd[rt]=rbd[RR];
sum[rt]=sum[LL]+sum[RR]-(!rbd[LL]&&!lbd[RR]);
}
void build(int l,int r,int rt){
sum[rt]=1;
col[rt]=lbd[rt]=rbd[rt]=0;
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) {
col[rt]+=c;
pushup(rt,l,r);
return ;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
if(col[rt]) return;
pushup(rt,l,r);
}
int main(){
int n,i,j,t,num,ca=1;
scanf("%d",&t);
while(t--){
int cnt=0;
scanf("%d%d",&num,&n);
for(i=0;i<n;i++){
scanf("%s%d%d",q[i].op,&q[i].l,&q[i].r);
x[cnt++]=q[i].l;x[cnt++]=q[i].r;
}
x[cnt++]=0;x[cnt++]=num-1;
sort(x,x+cnt);
int m=1;
for(i=1;i<cnt;i++) if(x[i]!=x[i-1]) x[m++]=x[i];
for(i=m-1;i>=1;i--) if(x[i]!=x[i-1]+1) x[m++]=x[i-1]+1;
sort(x,x+m);
build(0,m-1,1);
printf("Case #%d:\n",ca++);
for(i=0;i<n;i++){
int l=lower_bound(x,x+m,q[i].l)-x;
int r=lower_bound(x,x+m,q[i].r)-x;
int c=q[i].op[0]=='p'?1:-1;
update(l,r,c,0,m-1,1);
printf("%d\n",sum[1]);
}
}
return 0;
}



 

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