BZOJ3226 SDOI2008 校门外的区间 线段树/平衡树

大体说一下思路:将开区间和闭区间拆成两个点,用线段树或者平衡树(论练代(Do)码(Die)的重要性……)来维护01串就好。

40分代码,实在懒得调了QAQ

const int MAXN=65536*2;
typedef struct NODE{
    int l,r;
    bool inv,same,v;
    NODE *lchild,*rchild;
    NODE(){}
    NODE(int _l,int _r):l(_l),r(_r),v(0),inv(0),same(0){}
} *TREE;
TREE root;
char order[6+2];
bool flag;

int read(){
    int x=0,f=0;

    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='(')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    if(ch==')') f=1;

    return x*2-f;
}

void Pushdown(TREE &x){
    if(x->l==x->r){
        x->v^=1;
        return;
    }
    if(x->same){
        x->lchild->v=x->rchild->v=x->v;
        x->lchild->inv=x->rchild->inv=0;
        x->lchild->same=x->rchild->same=1,x->same=0;
    }
    x->lchild->inv^=x->inv,x->rchild->inv^=x->inv;
}

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 Change(TREE &x,int l,int r,bool v){
    if(l>r) return;
    if(x->l>=l && x->r<=r){
        x->same=1,x->v=v,x->inv=0;
        return;
    }

    Pushdown(x);

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

void Inverse(TREE &x,int l,int r){
    if(l>r) return;
    if(x->l>=l && x->r<=r){
        x->inv^=1,x->v^=1;
        return;
    }

    Pushdown(x);

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

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

    Pushdown(x);

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

int main(){
    Build(root,1,MAXN);

    int a,b;
    while(scanf("%s",order)!=EOF){
        a=read(),b=read();
        a+=2,b+=2;

        if(order[0]=='U') Change(root,a,b,1);
        if(order[0]=='I') Change(root,1,a-1,0),Change(root,b+1,MAXN,0);
        if(order[0]=='D') Change(root,a,b,0);
        if(order[0]=='C') Change(root,1,a-1,0),Change(root,b+1,MAXN,0),Inverse(root,a,b);
        if(order[0]=='S') Inverse(root,a,b);
    }

	for(int i=1,s=-1,t=-1;i<=MAXN;i++)
		if(Query(root,i)){
			if(s==-1) s=i;
			t=i;
		}
		else{
			if(s!=-1){
				if(s&1) printf("(");
				else printf("[");
				cout << (s>>1)-1 << "," << ((t+1)>>1)-1;
				if(t&1) printf(") ");
				else printf("] ");
			}
			s=t=-1;
		}

    return 0;
}
平衡树代码……Select在处理0边界的时候死活调不出来了,希望哪位神犇能讲一下……

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=65536*2;
typedef struct NODE{
    int c;
    bool v,same,inv;
    NODE *child[2],*f;
} *TREE;
TREE root,Null;
char order[6+2];
bool flag;

int read(){
    int x=0,f=0;

    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='(')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    if(ch==')') f=1;

    return x*2-f;
}

TREE NewNode(TREE f){
    TREE x=new NODE;
    x->f=f,x->child[0]=x->child[1]=Null;
    x->c=1,x->v=x->same=x->inv=0;
    return x;
}

void Initialization(){
    Null=NewNode(0),Null->c=0;
    root=NewNode(Null);
    root->child[1]=NewNode(root);
}

void Pushup(TREE x){
    if(x==Null) return;
    x->c=x->child[0]->c+x->child[1]->c+1;
}

void Pushdown(TREE x){
    if(x==Null) return;
    if(x->same){
        x->child[0]->same=x->child[1]->same=1;
        x->child[0]->v=x->child[1]->v=x->v;
        x->child[0]->inv=x->child[1]->inv=0;
        x->same=0;
    }
    if(x->inv){
        x->child[0]->inv^=1,x->child[1]->inv^=1;
        x->inv=0,x->v^=1;
    }
}

void Rotate(TREE x,bool t){
    TREE y=x->f;
    Pushdown(x->child[0]),Pushdown(x->child[1]),Pushdown(y->child[t]);

    y->child[!t]=x->child[t],x->child[t]->f=y,x->f=y->f;
    if(y->f->child[0]==y) y->f->child[0]=x;
    else y->f->child[1]=x;
    y->f=x,x->child[t]=y;

    Pushup(y),Pushup(x);
    if(y==root) root=x;
}

void Splay(TREE x,TREE y){
    Pushdown(x);
    while(x->f!=y)
        if(x->f->f==y)
            if(x->f->child[0]==x) Rotate(x,1);
            else Rotate(x,0);
        else if(x->f->f->child[0]==x->f)
            if(x->f->child[0]==x) Rotate(x->f,1),Rotate(x,1);
            else Rotate(x,0),Rotate(x,1);
        else
            if(x->f->child[0]==x) Rotate(x,1),Rotate(x,0);
            else Rotate(x->f,0),Rotate(x,0);
}

void Select(int p,TREE y){
    TREE x=root;Pushdown(x);
    while(p!=x->child[0]->c+1){
        if(p<=x->child[0]->c) x=x->child[0];
        else p-=x->child[0]->c+1,x=x->child[1];
        Pushdown(x);
    }
    Splay(x,y);
}

void Build(int p,int n){
    TREE s,t;
    s=t=NewNode(Null);
    for(int i=2;i<=n;i++) t=t->child[1]=NewNode(t);

    Select(p+1,Null),Select(p+2,root);
    root->child[1]->child[0]=s,s->f=root->child[1];
    Splay(t,Null);
}

void Change(int p,int n,bool v){
    Select(p-1,Null),Select(p+n,root);
    root->child[1]->child[0]->v=v;
    root->child[1]->child[0]->inv=0;
    root->child[1]->child[0]->same=1;
    Splay(root->child[1]->child[0],Null);
}

void Inverse(int p,int n){
    Select(p-1,Null),Select(p+n,root);
    root->child[1]->child[0]->inv^=1;
    Splay(root->child[1]->child[0],Null);
}

bool Query(int p){
    TREE x=root;Pushdown(x);
    while(p!=x->child[0]->c+1){
        if(p<=x->child[0]->c) x=x->child[0];
        else p-=x->child[0]->c+1,x=x->child[1];
        Pushdown(x);
    }
    return x->v;
}

int main(){
    Initialization();
    Build(0,MAXN);

    int a,b;
    while(scanf("%s",order)!=EOF){
        a=read(),b=read();
        a+=2,b+=2;
        if(order[0]=='U') Change(a,b-a+1,1);
        if(order[0]=='I') Change(b+1,MAXN-b,0);
        if(order[0]=='D') Change(a,b-a+1,0);
        if(order[0]=='C') Change(1,a-1,0),Change(b+1,MAXN-b,0),Inverse(a,b-a+1);
        if(order[0]=='S') Inverse(a,b-a+1);
    }

	int s=-1,t=-1;
	for(int i=1;i<=MAXN;i++){
		if(Query(i)){
			if(s==-1) s=i;
			t=i;
		}
		else{
			if(s!=-1){
				if(s&1) cout << "(";
				else cout << "[";
				cout << (s>>1)-1 << "," << ((t+1)>>1)-1;
				if(t&1) cout << ") ";
				else cout << "] ";
			}
			t=s=-1,flag=1;
		}
	}
	if(!flag) cout << "empty set" << endl;

    return 0;
}



你可能感兴趣的:(BZOJ3226 SDOI2008 校门外的区间 线段树/平衡树)