1. 程式人生 > >Codeforce 915E(線段樹動態開點)

Codeforce 915E(線段樹動態開點)

題意:Alex高中畢業了,他現在是大學新生。雖然他學習程式設計,但他還是要上體育課,這對他來說完全是一個意外。快要期末了,但是不幸的Alex的體育學分還是零蛋!
Alex可不希望被開除,他想知道到期末還有多少天的工作日,這樣他就能在這些日子裡修體育學分。但是在這裡計算工作日可不是件容易的事情:
從現在到學期結束還有 n 天(從 1 到 n 編號),他們一開始都是工作日。接下來學校的工作人員會依次發出 q 個指令,每個指令可以用三個引數 l,r,k 描述:
如果 k=1,那麼從 l 到 r (包含端點)的所有日子都變成非工作日。
如果 k=2,那麼從 l 到 r (包含端點)的所有日子都變成工作日。
幫助Alex統計每個指令下發後,剩餘的工作日天數
(1≤n≤10^9,1≤q≤3*10^5)

程式碼:

#include <map>
#include <stack>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int siz=15000005;
int n,m,id;
int ll[siz],rr[siz],sum[siz],lazy[siz];
void pushdown(int l,int r,int rt){
    if(lazy[rt]!=-1){
        int m=(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]]=(m-l+1)*lazy[rt];
            sum[rr[rt]]=(r-m)*lazy[rt];
        }
        lazy[rt]=-1;
    }
}
void change(int L,int R,int p,int l,int r,int &rt){
    if(!rt) rt=++id;                            //動態開點就是什麼時候用什麼時候開點
    if(L<=l&&r<=R){
        lazy[rt]=p;
        sum[rt]=p*(r-l+1);
        return;
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    if(L<=m)
    change(L,R,p,l,m,ll[rt]);
    if(R>m)
    change(L,R,p,m+1,r,rr[rt]);
    sum[rt]=sum[ll[rt]]+sum[rr[rt]];
}
int main(){                                     //因為n特別大,所以可以直接動態開點
    int i,j,x,y,z,rt;                           //複雜度O(qlogn),複雜度可能沒有直接
    while(scanf("%d%d",&n,&m)!=EOF){            //離散化O(qlogq)優秀,但是實現起來比較簡單 
        id=rt=0;
        memset(ll,0,sizeof(ll));
        memset(rr,0,sizeof(rr));
        memset(sum,0,sizeof(sum));
        memset(lazy,-1,sizeof(lazy));
        for(i=1;i<=m;i++){
            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;
}
/*
10
3
2 3 1
1 5 1
4 6 1
*/