BZOJ3226 SDOI2008 校门外的区间 线段树

题意:给定一个空的数集,要求维护:1、区间求并 2、区间求交 3、区间求差 4、区间异或。每次操作后原区间变为操作后的区间,每个操作的区间可开可闭,求所有操作后的区间

题解:把每个点拆成开和闭两个,线段树维护就好。最后统计答案的时候暴力枚举每个位置即可

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define Lim (1<<17)

typedef struct Node{
    int l,r;
    bool Rev,v,Same;
    Node *lchild,*rchild;
    Node(){}
    Node(int _l,int _r):l(_l),r(_r),v(0),Rev(0),Same(1),lchild(0),rchild(0){}
} *Tree;
Tree Root;
int M;
char a,b,t;
bool Flag;

void Build(Tree &x,int l,int r){
    x=new Node(l,r);
    if(l==r) return;

    int m=(l+r)>>1;
    Build(x->lchild,l,m),Build(x->rchild,m+1,r);
}

void Pushdown(Tree &x){
    if(x->l==x->r) return;
    if(x->Same){
        x->Same=0,x->lchild->Same=x->rchild->Same=1;
        x->lchild->v=x->rchild->v=x->v,x->lchild->Rev=x->rchild->Rev=0;
    }
    if(x->Rev){
        x->Rev=0;
        x->lchild->Rev^=1,x->rchild->Rev^=1;
    }
}

void Update(Tree &x,int l,int r,bool v){
    if(l<=x->l && x->r<=r){
        x->Rev=0,x->Same=1,x->v=v;
        return;
    }
    Pushdown(x);

    int m=(x->l+x->r)>>1;
    if(l<=m) Update(x->lchild,l,r,v);
    if(r>m) Update(x->rchild,l,r,v);
}

void Reverse(Tree &x,int l,int r){
    if(l<=x->l && x->r<=r){
        x->Rev^=1;
        return;
    }
    Pushdown(x);

    int m=(x->l+x->r)>>1;
    if(l<=m) Reverse(x->lchild,l,r);
    if(r>m) Reverse(x->rchild,l,r);
}

bool Query(Tree &x,int p){
    Pushdown(x);
    if(x->l==x->r) return x->v;

    int m=(x->l+x->r)>>1;
    if(p<=m) return Query(x->lchild,p);
    else return Query(x->rchild,p);
}

void Visit(Tree &x){
    if(x->Same){
        x->v^=x->Rev;
        return;
    }
    Pushdown(x);
    Visit(x->lchild),Visit(x->rchild);
}

int main(){
    Build(Root,0,Lim);
    int l,r;
    while(scanf("%c %c%d,%d%c\n",&t,&a,&l,&r,&b)!=EOF){
        l<<=1,r<<=1;
        if(a=='(') l++;
        if(b==')') r--;

        if(t=='U') Update(Root,l,r,1);
        if(t=='I'){
            if(l) Update(Root,0,l-1,0);
            if(r<Lim) Update(Root,r+1,Lim,0);
        }
        if(t=='D') Update(Root,l,r,0);
        if(t=='C'){
            if(l) Update(Root,0,l-1,0);
            if(r<Lim) Update(Root,r+1,Lim,0);
            Reverse(Root,l,r);
        }
        if(t=='S') Reverse(Root,l,r);
    }

    Visit(Root);
    for(int i=0,p=-1;i<=Lim;i++){
        if(Query(Root,i) && p==-1) p=i;
        if(!Query(Root,i) && p!=-1){
            cout << (p&1?"(":"[") << (p>>1) << "," << (i>>1) << (i&1?"]":")") << " ";
            Flag=1,p=-1;
        }
    }
    if(!Flag) cout << "empty set" << endl;

    return 0;
}
View Code

 

posted @ 2017-03-18 22:40  WDZRMPCBIT  阅读(132)  评论(0编辑  收藏  举报