3年没写线段树题了,今天帮小学弟水了棵线段树,想不到现在依然有看到Accepted的鸡冻哈哈哈

题目大意:给一个区间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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值