POJ3225 Help with Intervals(区间操作)

纯属抄袭胡浩大神的题解。。。看了N久才看懂o(╯□╰)o,果然智商拙计,学习到了一种处理开区间的方法(感觉好神奇),当个搬运工。。。

题目大意:

区间操作,交,并,补等

题解:

我们一个一个操作来分析:(用0和1表示是否包含区间,-1表示该区间内既有包含又有不包含)

U:把区间[l,r]覆盖成1

I:把[-∞,l)(r,∞]覆盖成0

D:把区间[l,r]覆盖成0

C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换

S:[l,r]区间0/1互换

成段覆盖的操作很简单,比较特殊的就是区间0/1互换这个操作,我们可以称之为异或操作

很明显我们可以知道这个性质:当一个区间被覆盖后,不管之前有没有异或标记都没有意义了

所以当一个节点得到覆盖标记时把异或标记清空

而当一个节点得到异或标记的时候,先判断覆盖标记,如果是0或1,直接改变一下覆盖标记,不然的话改变异或标记

开区间闭区间只要数字乘以2就可以处理(偶数表示端点,奇数表示两端点间的区间)

线段树功能:update:成段替换,区间异或 query:简单hash

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l , m , s << 1
#define rson m+1 , r , s << 1 | 1
#define MAXN 150000
int setv[MAXN<<2],Xor[MAXN<<2];
bool hash[MAXN];
void FXor(int s)
{
    if(setv[s]!=-1) setv[s]^=1;
    else
        Xor[s]^=1;
}
void PushDown(int s)
{
    if(setv[s]!=-1) {
        setv[s<<1]=setv[s<<1|1]=setv[s];
        Xor[s<<1]=Xor[s<<1|1]=0;
        setv[s]=-1;
    }
    if(Xor[s]==1) {
        FXor(s<<1);
        FXor(s<<1|1);
        Xor[s]=0;
    }
}
void update(char op,int ql,int qr,int l,int r,int s)
{
    if(ql<=l&&r<=qr) {
        if(op=='U') {
            setv[s]=1;
            Xor[s]=0;
        } else if(op=='D') {
            setv[s]=0;
            Xor[s]=0;
        } else if(op=='C'||op=='S')
            FXor(s);
        return;
    }
    PushDown(s);
    int m=(l+r)>>1;
    if(ql<=m) update(op,ql,qr,lson);
    else  if(op=='I'||op=='C') Xor[s<<1]=setv[s<<1]=0;
    if(qr>m) update(op,ql,qr,rson);
    else if(op=='I'||op=='C') Xor[s<<1|1]=setv[s<<1|1]=0;
}
void query(int l,int r,int s)
{
    if(setv[s]==1) {
        for(int i=l; i<=r; i++)
            hash[i]=true;
        return;
    } else if(setv[s]==0) return;
    if(l==r) return;
    PushDown(s);
    int m=(l+r)>>1;
    query(lson);
    query(rson);
}
int main(void)
{
    char op,a,b;
    int l,r;
    setv[1]=Xor[1]=0;
    memset(hash,false,sizeof(hash));
    while(scanf("%c %c%d,%d%c\n",&op,&a,&l,&r,&b)!=EOF) {
        l<<=1;
        r<<=1;
        if(a=='(') l++;
        if(b==')') r--;
        update(op,l,r,0,MAXN,1);
    }
    query(0,MAXN,1);
    int s=-1,t;
    bool flag=false;
    for(int i=0; i<MAXN; i++)
        if(hash[i]) {
            if(s==-1) s=i;
            t=i;
        } else if(s!=-1)  {
            if(flag) printf(" ");
            flag=true;
            printf("%c%d,%d%c",s&1?'(':'[',s>>1,(t+1)>>1,t&1?')':']');
            s=-1;
        }
    if(!flag) printf("empty set");
    printf("\n");
    return 0;
}

原文地址:https://www.cnblogs.com/zjbztianya/p/3092085.html