(中等) 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:

Operation Notation
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:

Command Semantics
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\n");
        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;
}

时间: 2024-10-25 17:02:36

(中等) POJ 3225 Help with Intervals , 线段树+集合。的相关文章

poj 3225 Help with Intervals(线段树)

题目链接:poj 3225 Help with Intervals 题目大意:模拟集合操作,输出最终的集合. 解题思路:线段树. U l r:[l,r]区间置为1 I l r:[0,l),(r,maxn]置为0 D l r:[l,r]区间置为0 C l r:[0,l),(r,maxn]置为0,[l,r]区间取逆 S l r:[l,r]区间取逆. 然后基本水水的线段树,注意一下区间开和闭. #include <cstdio> #include <cstring> #include &

poj 3225 Help with Intervals(线段树,区间更新)

Help with Intervals Time Limit: 6000MS   Memory Limit: 131072K Total Submissions: 12474   Accepted: 3140 Case Time Limit: 2000MS Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While Ikki is working on g

(中等) POJ 1436 Horizontally Visible Segments , 线段树+区间更新。

Description There is a number of disjoint vertical line segments in the plane. We say that two segments are horizontally visible if they can be connected by a horizontal line segment that does not have any common points with other vertical segments.

POJ 3225 Help with Intervals(线段树)

POJ 3225 Help with Intervals 题目链接 集合数字有的为1,没有为0,那么几种操作对应就是置为0或置为1或者翻转,这个随便推推就可以了,然后开闭区间的处理方式就是把区间扩大成两倍,偶数存点,奇数存线段即可 代码: #include <cstdio> #include <cstring> #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) const int N = 65536

poj 3225 Help with Intervals

http://poj.org/problem?id=3225 题意:对集合进行交.并.差.异或四种操作,输出几步操作的之后的集合. U [a,b]  :可以将[a,b]全部置为1:  I [a,b] :可以将[a,b]之外的全部置为0:   S-[a,b] :将[a,b]全部置为0:  [a,b]-s  :将[a,b]之外的全部置为0,[a,b]取反.  I [a,b]  :将[a,b]取反. 然后用线段树维护区间. 1 #include <cstdio> 2 #include <cst

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 ti

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿