1. 程式人生 > >CodeForces - 915E 動態開點線段樹||離散化線段樹

CodeForces - 915E 動態開點線段樹||離散化線段樹

 題意:

給定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
*/