zoukankan      html  css  js  c++  java
  • (中等) POJ 3225 Help with Intervals , 线段树+集合。

    Description

      LogLoader, Inc. is a company specialized in providing products for analyzing logs. While Ikki is working on graduation design, he is also engaged in an internship at LogLoader. Among his tasks, one is to write a module for manipulating time intervals, which have confused him a lot. Now he badly needs your help.

      In discrete mathematics, you have studied several basic set operations, namely union, intersection, relative complementation and symmetric difference, which naturally apply to the specialization of sets as intervals.. For your quick reference they are summarized in the table below:

    OperationNotation

    Definition

    Union A ∪ B {x : x ∈ A or x ∈ B}
    Intersection A ∩ B {x : x ∈ A and x ∈ B}
    Relative complementation A − B {x : x ∈ A but x ∉ B}
    Symmetric difference A ⊕ B (A − B) ∪ (B − A)

      Ikki has abstracted the interval operations emerging from his job as a tiny programming language. He wants you to implement an interpreter for him. The language maintains a set S, which starts out empty and is modified as specified by the following commands:

    CommandSemantics
    U T S ← S ∪ T
    I T S ← S ∩ T
    D T S ← S − T
    C T S ← T − S
    S T S ← S ⊕ T
      
      题目大致就是说对一个线段进行操作,然后问集合。
      首先要处理的是开区间和闭区间的表示,把所有数乘以2,开的话+1或-1(根据在左边还是右边而定)。
      然后就是集合的操作,并集的话直接覆盖为1,交集的话T的补集覆盖为0,D得话T覆盖为0,C的话先把T的补集覆盖为0,然后T区间取反,S的话T区间取反就好。
      有两个操作,所以维护两个操作,覆盖和取反。
      这里要注意,取反之后覆盖的话要把取反标记为0。
      另外,覆盖的话可以用-1为没有覆盖过,0为覆盖0,1为覆盖1,。
      也可以用0为没覆盖过,1为覆盖1,然后覆盖0的操作等价于覆盖1,然后取反。(我就是这样做的。)
     
    代码如下:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define lson L,M,po*2
    #define rson M+1,R,po*2+1
    
    using namespace std;
    
    const int N=65535*2;
    
    bool COL[140000*4]={0};
    bool XOR[140000*4]={0};
    bool vis[140000]={0};
    bool have=0;
    
    void pushDown(int po)
    {
        if(COL[po])
        {
            COL[po*2]=COL[po*2+1]=COL[po];
            COL[po]=0;
            XOR[po*2]=XOR[po*2+1]=0;            //  don't forget!!!
        }
    
        if(XOR[po])
        {
            XOR[po*2]=!XOR[po*2];
            XOR[po*2+1]=!XOR[po*2+1];
            XOR[po]=0;
        }
    }
    
    void updateC(int ul,int ur,bool type,int L,int R,int po)
    {
        if(ul>ur)
            return;
    
        if(ul<=L&&ur>=R)
        {
            XOR[po]=0;
            COL[po]=type;
    
            return;
        }
    
        pushDown(po);
    
        int M=(L+R)/2;
    
        if(ul<=M)
            updateC(ul,ur,type,lson);
        if(ur>M)
            updateC(ul,ur,type,rson);
    }
    
    void updateX(int ul,int ur,int L,int R,int po)
    {
        if(ul>ur)
            return;
    
        if(ul<=L&&ur>=R)
        {
            XOR[po]=!XOR[po];
    
            return;
        }
    
        pushDown(po);
    
        int M=(L+R)/2;
    
        if(ul<=M)
            updateX(ul,ur,lson);
        if(ur>M)
            updateX(ul,ur,rson);
    }
    
    void query(int L,int R,int po)
    {
        if(L==R)
        {
            vis[L]=COL[po]^XOR[po];
    
            if(vis[L])
                have=1;
    
            return;
        }
    
        pushDown(po);
    
        int M=(L+R)/2;
    
        query(lson);
        query(rson);
    }
    
    int main()
    {
        char C;
        char t1,t2;
        int a,b;
        int x,y;
    
        while(cin>>C)
        {
            scanf(" %c%d,",&t1,&a);
            scanf("%d%c",&b,&t2);
    
            a*=2;
            b*=2;
    
            if(t1=='(')
                ++a;
            if(t2==')')
                --b;
    
            switch(C)
            {
            case 'U':
                updateC(a,b,1,0,N,1);
                break;
    
            case 'I':
                updateC(0,a-1,1,0,N,1);
                updateX(0,a-1,0,N,1);
                updateC(b+1,N,1,0,N,1);
                updateX(b+1,N,0,N,1);
                break;
    
            case 'D':
                updateC(a,b,1,0,N,1);
                updateX(a,b,0,N,1);
                break;
    
            case 'C':
                updateC(0,a-1,1,0,N,1);
                updateX(0,a-1,0,N,1);
                updateC(b+1,N,1,0,N,1);
                updateX(b+1,N,0,N,1);
                updateX(a,b,0,N,1);
                break;
    
            case 'S':
                updateX(a,b,0,N,1);
                break;
    
            }
        }
    
        query(0,N,1);
    
        if(!have)
        {
            printf("empty set
    ");
            return 0;
        }
    
        bool has=0;
        for(int i=0;i<=N+1;++i)
        {
            if(vis[i])
            {
                if(!has)
                {
                    has=1;
                    if(i%2)
                        printf("(%d,",(i-1)/2);
                    else
                        printf("[%d,",i/2);
                }
            }
            else
            {
                if(has)
                {
                    has=0;
                    if((i-1)%2)
                        printf("%d) ",i/2);
                    else
                        printf("%d] ",(i-1)/2);
                }
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    vim实用技巧总结
    configure, make, make install都做了什么
    替换ubuntu 14.04的源
    从源码Build vim以及打包.deb
    Vimperator技巧
    搭建Gitlab
    [转] 你真的会写单例模式吗——Java实现
    笔记本开临时Wifi
    Ubuntu 12.04 修改键盘映射
    oracle查看用户所在的表空间
  • 原文地址:https://www.cnblogs.com/whywhy/p/4194727.html
Copyright © 2011-2022 走看看