题目大意:给一个区间1~10^10,然后Q个操作有更新,有询问,Q的范围是1~10^5,明显是一个离散化+区间更新的线段树水题传送门,这里更新需要注意lay的思想,也就是延迟更新,具体就是push down和push up操作,具体看代码;
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAX=204002;
int a[MAX*2];
int op[MAX][3];
struct node{
int l,r,ok;
}tree[MAX*8];
void build(int pos,int l,int r) {
tree[pos].l=l;
tree[pos].r=r;
tree[pos].ok = a[tree[pos].r-1] - a[tree[pos].l-1]+1;
if(l==r)
return;
int mid=(l+r)>>1;
build(pos*2,l,mid);
build(pos*2+1,mid+1,r);
tree[pos].ok = tree[pos*2].ok+ tree[pos*2+1].ok;
}
void update(int pos,int l,int r){
if(l<=tree[pos].l&&tree[pos].r<=r) {
tree[pos].ok = 0;
return;
}
if(tree[pos].ok==0) { //lay :push down
tree[pos*2].ok = 0;
tree[pos*2+1].ok = 0;
}
int mid=(tree[pos].l+tree[pos].r)>>1;
if(r<=mid)
update(pos*2,l,r);
else if(l>mid)
update(pos*2+1,l,r);
else {
update(pos*2,l,mid);
update(pos*2+1,mid+1,r);
}
tree[pos].ok = tree[pos*2].ok + tree[pos*2+1].ok; //lay : push up
}
int query(int pos,int l,int r){
if(l<=tree[pos].l&&tree[pos].r<=r) {
return tree[pos].ok;
}
int mid=(tree[pos].l+tree[pos].r)>>1;
if(tree[pos].ok==0) {
tree[pos*2].ok = 0;
tree[pos*2+1].ok = 0;
}
if(r<=mid)
return query(pos*2,l,r);
else if(l>mid)
return query(pos*2+1,l,r);
else {
return query(pos*2,l,mid)+ query(pos*2+1,mid+1,r);
}
}
int main(){
int N,Q;
cin>>N>>Q;
int index = 0;
for(int i=0;i<Q;i++) {
scanf("%d%d%d",&op[i][0],&op[i][1],&op[i][2]);
a[index++]=op[i][1];
a[index++]=op[i][2];
}
//两次离散化,防止有相邻的数据
sort(a,a+index);
int n=unique(a,a+index)-a;
int t = 0;
for(int i=1;i<n;i++){
if(a[i]-a[i-1]!=1){
a[n+t] = a[i-1]+1;
t++;
}
}
sort(a,a+n+t);
n=unique(a,a+n+t)-a;
build(1,1,n);
for(int i=0;i<Q;i++) {
if(op[i][0]==1) {
update(1, lower_bound(a,a+n,op[i][1])-a+1 , lower_bound(a,a+n,op[i][2])-a+1 );
}else {
printf("%d\n",query(1, lower_bound(a,a+n,op[i][1])-a+1, lower_bound(a,a+n,op[i][2])-a+1 ));
}
}
return 0;
}