1. 程式人生 > >線段樹之線段操作之陳老師的福利

線段樹之線段操作之陳老師的福利

題面:

在數軸上進行一系列操作。每次操作有兩種型別,一種是線上段[a,b]上塗上顏色,另一種將[a,b]上的顏色擦去。
問經過一系列的操作後,有多少條單位線段[k,k+1]被塗上了顏色

Input:

第一行兩個整數n,m,表示數軸從0到n,運算元為m
接下來m行,每行三個整數op,a,b,op=0時表示將[a,b]上的顏色擦去,op=1時表示線上段[a,b]上塗上顏色
n,m<=100000

Output:

輸出一個整數,表示有多少條單位線段[k,k+1]被塗上了顏色

Solution:

線段樹,tree陣列記錄當前區間被染色的長度,如果當前區間全部被染色,則令tree值等於當前區間長度,值得一提的是,要記錄區間長度,只需要記錄l+1到r的點數就行了

Code:

#include<bits/stdc++.h>
#define N 400001
using namespace std;
int n,m;
struct sgt{
    #define ls (q<<1)
    #define rs (q<<1|1)
    int tree[N],lazy[N];
    void add(int l,int r,int q,int v){
        tree[q]=r-l+1;
        if(v==-1)tree[q]=0;
        lazy[q]=v;
    }
    void pushdown(int l,int r,int q){
        if(lazy[q]==0)return ;
        int mid=(l+r)>>1;
        add(l,mid,ls,lazy[q]);
        add(mid+1,r,rs,lazy[q]);
        lazy[q]=0;
    }
    void change(int l,int r,int L,int R,int q,int v){
        if(l>R||r<L)return ;
        if(l>=L&&r<=R)return add(l,r,q,v);
        pushdown(l,r,q);
        int mid=(l+r)>>1;
        if(mid>=L)change(l,mid,L,R,ls,v);
        if(mid<R)change(mid+1,r,L,R,rs,v);
        tree[q]=tree[ls]+tree[rs];
    }
    int ans(){
        pushdown(1,n,1);
        return tree[1];
    }
}T;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=m;i++){
        int opt,x,y;
        opt=read();x=read();y=read();
        if(opt==0)opt--;
        x++;
        T.change(1,n,x,y,1,opt);
    }
    printf("%d",T.ans());
    return 0;
}