题意:
给定1-n的一段空区间,每次给出 x y z 的询问,z == 1 时将 x - y 区间全部填充,否则为空,问最后一共有多少空区间
分析:
很明显的线段树题目,不过主要是想学习以下动态开点,不过数组范围自己一时间也还不懂怎么处理。看cf上很多大佬STL做的,很是骚,%%%
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
int ll[maxn*50],rr[maxn*50],sum[maxn*50],lazy[maxn*50];
int id;
void push_down(int l,int r,int &rt){
if(lazy[rt]==-1) return;
int mid=l+r>>1;
if(l!=r){ //不是叶子节点则需要开辟左节点跟右节点。
if(ll[rt]==0) ll[rt]=++id;
if(rr[rt]==0) rr[rt]=++id;
lazy[ll[rt]]=lazy[rt];
lazy[rr[rt]]=lazy[rt];
sum[ll[rt]]=(mid-l+1)*lazy[rt];
sum[rr[rt]]=(r-mid)*lazy[rt];
}
lazy[rt]=-1;
}
void change(int tl,int tr,int v,int l,int r,int &rt){
if(!rt) rt=++id; //动态开点就是什么时候用什么时候开点
if(r<tl||tr<l) return;
if(tl<=l&&r<=tr){
lazy[rt]=v;
sum[rt]=(r-l+1)*v;
return;
}
push_down(l,r,rt);
int mid=l+r>>1;
change(tl,tr,v,l,mid,ll[rt]);
change(tl,tr,v,mid+1,r,rr[rt]);
sum[rt]=sum[ll[rt]]+sum[rr[rt]];
}
int main(){
int l,r,x,y,z,rt,n,m;
while(scanf("%d%d",&n,&m)!=EOF){
id=rt=0;
memset(ll,0,sizeof ll);
memset(rr,0,sizeof rr);
memset(sum,0,sizeof sum);
memset(lazy,-1,sizeof lazy);
while(m--){
scanf("%d%d%d",&x,&y,&z);
if(z==1) change(x,y,1,1,n,rt);
else change(x,y,0,1,n,rt);
printf("%d\n",n-sum[1]);
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e6+10;
int x[maxn],y[maxn],f[maxn];
struct node{
int sum,lazy;
}p[maxn<<2];
int id[maxn*6];
void build(int l,int r,int i){
p[i].sum=0;p[i].lazy=-1;
if(l==r) return ;
int mid=l+r>>1;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
}
void update(int l,int r,int i){
if(p[i].lazy==-1) return ;
int mid=l+r>>1;
p[i<<1].sum=(id[mid]-id[l-1])*p[i].lazy;
p[i<<1|1].sum=(id[r]-id[mid])*p[i].lazy;
p[i<<1].lazy=p[i<<1|1].lazy=p[i].lazy;
p[i].lazy=-1;
}
void change(int tl,int tr,int i,int l,int r,int v){
if(tl>r||tr<l) return ;
if(tl<=l&&r<=tr){
p[i].sum=(id[r]-id[l-1])*v;
p[i].lazy=v;
return;
}
update(l,r,i);
int mid=l+r>>1;
change(tl,tr,i<<1,l,mid,v);
change(tl,tr,i<<1|1,mid+1,r,v);
p[i].sum=p[i<<1].sum+p[i<<1|1].sum;
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
int cnt=0;
id[++cnt]=1;
id[++cnt]=n;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x[i],&y[i],&f[i]);
id[++cnt]=x[i];
id[++cnt]=y[i];
}
sort(id+1,id+1+cnt);
cnt=unique(id+1,id+1+cnt)-(id+1);
int tot=cnt;
for(int i=2;i<=cnt;i++){
if(id[i]-id[i-1]>1) id[++tot]=id[i-1]+1>n?n:id[i-1]+1;
}
sort(id+1,id+1+tot);
cnt=unique(id+1,id+1+tot)-(id+1);
tot=cnt;
for(int i=cnt;i>1;i--){
if(id[i]-id[i-1]>1) id[++tot]=id[i]-1<1?1:id[i]-1;
}
sort(id+1,id+1+tot);
cnt=unique(id+1,id+1+tot)-(id+1);
build(1,cnt,1);
for(int i=1;i<=m;i++){
int xx=lower_bound(id+1,id+1+cnt,x[i])-id;
int yy=lower_bound(id+1,id+1+cnt,y[i])-id;
if(f[i]==1){
change(xx,yy,1,1,cnt,1);
}else change(xx,yy,1,1,cnt,0);
printf("%d\n",n-p[1].sum);
}
}
return 0;
}
/*
10 3
1 10 1
1 2 1
9 10 1
*/