3225 Help with Intervals

题意:

给你几个集合的操作,最后用不想交的集合表示这个集合。

最开始给定的S集合为空。

CommandSemantics
U TS ← S ∪ T
I TS ← S ∩ T
D TS ← S − T
C TS ← T − S
S TS ← S ⊕ T
千米那的字母就代表要进行的操作,后面总是给定一个集合T.

思路:

(虽然是在做线段树分类,但是拿到这道题的时候还是一点思路也没有)

首先是怎么来表示这个集合:

由于这个集合有包含端点和不包含端点两种,所以不能简单的用数字带表集合。

需要有数组来表示中间的那一段数字。

我们只需要把每个数字乘2,再对应是否包含端点操作就行了。



进行这样的一个操作后就可以利用线段树进行集合的操作了。

每个操作都可以对应一个操作:

U ::[l, r]置为1

I :(-oo, l) U (r, +oo) 置为0

D:[l, r] 置为0

C:(-oo, l) U (r, +oo)置为0,[l, r] ^ 1

S:[l, r] ^ 1

另外我们注意到如果一个集合都需要修改的化,就不需要进行异或操作了,只需要单纯的修改就可以了。

Code:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include<cctype>
#include<vector>

#define TEST

#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
    #define See(a) cout << #a << " = " << a << endl;
    #define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
    #define debug(a, s, e){ rep(_i, s, e) {cout << a[_i] << ' '; }cout << endl;}
    #define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee);}
#else
    #define See(a)
    #define See2(a, b)
    #define debug(a, s, e)
    #define debug2(a, s, e, ss, ee)
#endif

const int MAX = 2e9;
const int MIN = -2e9;
const int PI = acos(-1.0);
const double eps = 1e-8;

using namespace std;

#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

const int N = 1 << 17;

int f[N << 2], x[N << 2];
bool v[N];

void toXor(int rt)
{
    if(f[rt] != -1)<span style="font-family: Arial, Helvetica, sans-serif;">//如果需要改变,就不需要进行异或。</span>
    {
        f[rt] ^= 1;
    }
    else
    {
        x[rt] ^= 1;
    }
}

void pushDown(int rt)
{
    if(f[rt] != -1) //如果需要改变,就不需要进行异或。
    {
        f[rt << 1] = f[rt << 1 | 1] = f[rt];
        x[rt << 1] = x[rt << 1 | 1] = 0;
        f[rt] = -1;
    }
    if(x[rt])
    {
        toXor(rt << 1);
        toXor(rt << 1 | 1);
        x[rt] = 0;
    }
}

void update(int L, int R, char op, int l, int r, int rt)
{
    if(l >= L && r <= R)
    {
        if(op == 'U')
        {
            f[rt] = 1;
            x[rt] = 0;
        }
        else if(op == 'D')
        {
            f[rt] = 0;
            x[rt] = 0;
        }
        else if(op == 'C' || op == 'S')
        {
            toXor(rt);
        }
        return ;
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    if(L <= m)
    {
        update(L, R, op, lson);
    }
    else if(op == 'I' || op == 'C')//修改[l,r]集合外的断点
    {
        x[rt << 1] = f[rt << 1] = 0;
    }
    if(m < R)
    {
        update(L, R, op, rson);
    }
    else if(op == 'I' || op == 'C')<span style="font-family: Arial, Helvetica, sans-serif;">//修改[l,r]集合外的断点</span>
    {
        x[rt << 1 | 1] = f[rt << 1 | 1] = 0;
    }
}

void query(int l, int r, int rt)
{
    if(f[rt] == 1)
    {
        for(int i = l; i <= r; ++i)
        {
            v[i] = true;
        }
        return ;
    }
    else if(f[rt] == 0)
    {
        return ;
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    query(lson);
    query(rson);
}

int main()
{
    char op, l, r;
    int a, b;
    char ch[100];
    f[1] = x[1] = 0;
    while(gets(ch))
    {
        sscanf(ch, "%c %c%d,%d%c", &op, &l, &a, &b, &r);
        a = (l == '(' ? a * 2 + 1 : a * 2);
        b = (r == ')' ? b * 2 - 1 : b * 2);
        if(a > b)
        {
            if(op == 'I' || op == 'C')
            {
                f[1] = x[1] = 0;
            }
        }
        else
        {
           update(a, b, op, 0, N, 1);
        }
    }
    query(0, N, 1);
    int st = -1, ed = 0;
    bool hasFind = false;
    for(int i = 0; i <= N; ++i)
    {
        if(v[i])
        {
            if(st == -1)
            {
                st = i;
            }
            ed = i;
        }
        else
        {
            if(st != -1)
            {
                if(hasFind)
                {
                    printf(" ");
                }
                hasFind = true;
                printf("%c%d,%d%c", st & 1 ? '(' : '[', st >> 1, (ed + 1) >> 1, ed & 1 ? ')' : ']');
                st = -1;
            }
        }
    }
    if(!hasFind)
    {
        printf("empty set\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值