校门外的树线段树做法

#include
//包括所有常用头文件,有些版本不兼容
using namespace std;
struct node {  
    int left;  
    int right;  
    int count; 
}a[100010];  
int ans;  
void build(int l, int r, int k) {  
    a[k].left=l;  
    a[k].right=r; 
    a[k].count=1;  //设初值 
    if(l==r)  
        return;  
    build(l,(l+r)/2,k*2);  
    build((l+r)/2+1,r,k*2+1);  //继续创建
}  
void query(int l, int r, int k) {  
    if(a[k].left==l&&a[k].right==r)  { 
        a[k].count=0; 
        return ;  
    }//重合
    if(a[k].count==0)return;//已经没有树了,就不要搜了
    if(a[k].left == a[k].right)  //左右界重合
        return ;
    a[k].count=2;//有0有1标记
    if(r<=(a[k].left+a[k].right)/2)  
        query(l,r,k*2);  
    else if(l>(a[k].left + a[k].right)/2)  
        query(l,r,k*2+1);  
    else {  
        query(l, (a[k].left + a[k].right)/2, k*2);  
        query((a[k].left + a[k].right)/2+1, r, k*2+1);  
    }//继续搜
} 
void pluss(int k) {
    if(a[k].count==1){
        ans+=a[k].right-a[k].left+1;
        return;
    }//只要为一,代表子树都为一,累加
    if(a[k].count==2){
        pluss(k*2);
        pluss(k*2+1);
    }//只要是二,就代表还要搜
} 
int main(){
    int i,n,m,k,x,y,z;
    scanf("%d",&n);
    build(1,n+1,1);//建立一个线段树
    scanf("%d",&m);
    for(i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        query(x+1,y+1,1);//标记
    }
    pluss(1);//累加
    cout<return 0;
}

ps:这题就完美转化为校门外的线段树了,呵呵呵
再ps:不要担心爆系统栈,栈只会用log2(n)

你可能感兴趣的:(题解,线段树)