好吧,第一次写离散化的线段树,用的有点久,主要是因为网上有没有标程,所以自有自己一个人慢慢调,我也是心累,不过最后写出来了还是蛮开心的,啦啦啦
注意几点:
1.在离散化以后,各个点之间不再是连续的了,所以要加一个flag标记,查询这个节点为根的子树中有没有更改然后记录它的右子树中最左边的点和左子树中最右边的点,好减
2.每次更新sum的时候需要用到上面说的右子树中最左边的点和左子树中最右边的点,有点绕;
3.找到区间后直接返回sum,不必再减
4.在释放懒惰标记的时候,子树的flag标记也需要标记上
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 100020
#define ls u<<1,l,mid
#define rs u<<1|1,mid+1,r
using namespace std;
int n,q,cur[maxn*2],cnt;
struct node{
int l,r,sum,add,flag,ll,lr,rl,rr;
}nod[maxn*4];
struct edge{
int t,l,r;
}e[maxn*2];
bool cmp(int a,int b){return a<b;}
void push_up(int u){
nod[u].sum=nod[u<<1].sum+nod[u<<1|1].sum;
nod[u].ll=nod[u<<1].ll;nod[u].lr=nod[u<<1].rr;
nod[u].rl=nod[u<<1|1].ll;nod[u].rr=nod[u<<1|1].rr;
if(nod[u].flag)nod[u].sum+=nod[u<<1|1].ll-nod[u<<1].rr-1;
}
void push_down(int u){
if(!nod[u].add)return;
nod[u<<1].sum=nod[u<<1].r-nod[u<<1].l+1;
nod[u<<1|1].sum=nod[u<<1|1].r-nod[u<<1|1].l+1;
nod[u<<1].add=nod[u].add;
nod[u<<1|1].add=nod[u].add;
nod[u<<1].flag =nod[u<<1|1].flag =1;
nod[u].add=0;
}
void build(int u,int l,int r){
nod[u].l=cur[l];nod[u].r=cur[r];
if(l==r){
nod[u].ll=nod[u].rr=nod[u].lr=nod[u].rl=cur[l];
nod[u].sum=0;
return;
}
int mid=(l+r)>>1;
build(ls);
build(rs);
push_up(u);
}
void update(int u,int l,int r,int x,int y,int add){
if(nod[u].l==x&&nod[u].r==y){
nod[u].flag=1;
nod[u].add=add;
nod[u].sum=nod[u].r-nod[u].l+1;
return;
}
push_down(u);
int mid=(l+r)>>1;
if(x>cur[mid])update(rs,x,y,add);
else if(y<=cur[mid])update(ls,x,y,add);
else {
nod[u].flag=1;
update(ls,x,cur[mid],add);
update(rs,cur[mid+1],y,add);
}
push_up(u);
}
int query(int u,int l,int r,int x,int y){
if(x==nod[u].l&&y==nod[u].r ){
int ans=0;
if(!nod[u].flag )ans+=nod[u].rl-nod[u].lr -1;
return nod[u].r-nod[u].l+1-nod[u].sum;
}
push_down(u);
int mid=(l+r)>>1;
if(x>cur[mid])return query(rs,x,y);
else if(y<=cur[mid])return query(ls,x,y);
else{
int ans=0;
if(!nod[u].flag)ans+=nod[u].rl-nod[u].lr -1;
return query(ls,x,cur[mid])+query(rs,cur[mid+1],y)+ans;
}
}
int main(){
scanf("%d%d",&n,&q);
int a,b,c;
for(int i=1;i<=q;i++){
scanf("%d%d%d",&a,&b,&c);
cur[++cnt]=b;
cur[++cnt]=c;
e[i].t=a;e[i].l=b;e[i].r=c;
}
sort(cur+1,cur+1+cnt,cmp);
cnt=unique(cur+1,cur+1+cnt)-cur-1;
build(1,1,cnt);
for(int i=1;i<=q;i++){
if(e[i].t==1)update(1,1,cnt,e[i].l,e[i].r ,1);
else printf("%d\n",query(1,1,cnt,e[i].l ,e[i].r ));
//cout<<endl;
}
return 0;
}