[SDOI2008] 校门外的区间 - 线段树

U T 即将区间 \(T\) 范围赋值为 \(1\)

I T 即将区间 \(U - T\) 范围赋值为 \(0\)

D T 即将区间 \(T\) 赋值为 \(0\)

C T 由于 \(S=T-S=T(U-S)\),即将原状态取反后,将 \(U-T\) 范围赋值为 \(0\)

S T 即将区间 \(T\) 翻转

至于开闭区间,我们不妨把下标缩放到原来的两倍,然后在输入输出的时候讨论一下即可

这题的输入真的挺正常(鬼畜)

#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;

int a[N],tag[N],rev[N],n,m,t1,t2,t3;

void settag(int p) {
    rev[p]=0; tag[p]=1;
}

void setrev(int p) {
    rev[p]^=1;
}

void pushdown(int p) {
    if(tag[p]) {
        tag[p*2]=tag[p*2+1]=1;
        rev[p*2]=rev[p*2+1]=0; // Error
        tag[p]=0;
    }
    if(rev[p]) {
        rev[p*2]^=1;
        rev[p*2+1]^=1;
        rev[p]=0;
    }
}

void modify(int p,int l,int r,int ql,int qr,int ist,int isr) {
    if(ql > qr) return;
    if(l>qr || r<ql) return;
    if(l>=ql && r<=qr) {
        if(ist) settag(p);
        if(isr) setrev(p);
    }
    else {
        pushdown(p);
        modify(p*2,l,(l+r)/2,ql,qr,ist,isr);
        modify(p*2+1,(l+r)/2+1,r,ql,qr,ist,isr);
    }
}

void traverse(int p,int l,int r) {
    if(l==r) {
        if(tag[p] && !rev[p]) a[l]=1;
        else a[l]=0;
    }
    else {
        pushdown(p);
        traverse(p*2,l,(l+r)/2);
        traverse(p*2+1,(l+r)/2+1,r);
    }
}

int main() {
    n=65536*2;
    char op,p,q;
    while(~scanf("%c %c%d,%d%c\n",&op,&p,&t1,&t2,&q)) {
        ++t1, ++t2;
        if(p=='(') t1=t1*2+1;
        else t1=t1*2;
        if(q==')') t2=t2*2-1;
        else t2=t2*2;
        if(t1>t2) continue;
        if(op=='U') modify(1,1,n,t1,t2,1,0);
        if(op=='I') modify(1,1,n,2,t1-1,1,1), modify(1,1,n,t2+1,n,1,1);
        if(op=='D') modify(1,1,n,t1,t2,1,1);
        if(op=='C') modify(1,1,n,2,n,0,1), modify(1,1,n,2,t1-1,1,1), modify(1,1,n,t2+1,n,1,1);
        if(op=='S') modify(1,1,n,t1,t2,0,1);
    }
    traverse(1,1,n);
    int last=0,flag=0;
    for(int i=1;i<=n+1;i++) { // Error n->n+1
        if(last==0 && a[i]==1) last=i;
        if(last && a[i]==0) {
            int l=last, r=i-1;
            flag=1;
            if(l&1) printf("(%d,",l/2-1);
            else printf("[%d,",l/2-1);
            if(r&1) printf("%d) ",(r-1)/2);
            else printf("%d] ",(r-1)/2);
            last=0;
        }
    }
    if(flag==0) cout<<"empty set";
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12289916.html