POJ 3225——Help with Intervals(线段树,成段替换+区间异或+hash)

Help with Intervals

Time Limit: 6000MS   Memory Limit: 131072K
Total Submissions: 10444   Accepted: 2551
Case Time Limit: 2000MS

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

Input

The input contains exactly one test case, which consists of between 0 and 65,535 (inclusive) commands of the language. Each command occupies a single line and appears like

X T

where X is one of ‘U’, ‘I’, ‘D’, ‘C’ and ‘S’ and T is an interval in one of the forms (a,b)(a,b][a,b) and [a,b] (ab ∈ Z,
0 ≤ a ≤ b ≤ 65,535), which take their usual meanings. The commands are executed in the order they appear in the input.

End of file (EOF) indicates the end of input.

Output

Output the set S as it is after the last command is executed as the union of a minimal collection of disjoint intervals. The intervals should be printed on one line separated by single spaces and appear in increasing order of their endpoints. If S is
empty, just print “empty set” and nothing else.

Sample Input

U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]

Sample Output

(2,3)

——————————————————————分割线————————————————————

题目大意:

就是实现区间的交,并,补,异或操作

思路:

对于区间的开,闭,将区间乘2,开的话,左端点+1,右端点-1.奇数表示开,偶数表示闭

例如(3,6)变成[7,11],左右端点为奇数,所以左右为开,退回来的时候判断7为奇数,11也为奇数,就是( 7/2, (11+1)/2 )

覆盖标记0、1,-1  :0表示不包含,1表示包含,-1表示既有包含也有不包含

异或标记0、1:0表示没有标记,1表示有标记

则:

U L,R
将区间L,R覆盖为1

D L,R
将区间L,R覆盖为0

I L,R
将区间<L和>R覆盖为0

C L,R
将区间<L和>R覆盖为0,对区间L,R 0,1进行对换(异或)

S L,R
将区间L,R  0,1进行对换(异或)

对于覆盖标记,如果存在异或标记,则将异或标记清0

对于异或标记,优先考虑是否存在覆盖标记,如果存在,则对覆盖标记异或,否则对异或标记异或

PS:还要熟练掌握push_down的内涵才行~~~

#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=131071;
using namespace std;
bool hash[maxn+5];
int cover[maxn<<2],Xor[maxn<<2];
void fxor(int rt)
{
    if(cover[rt]!=-1) cover[rt]^=1;
    else Xor[rt]^=1;
}
void push_down(int rt)
{
    if(cover[rt]!=-1){
        cover[rt<<1]=cover[rt<<1|1]=cover[rt];
        cover[rt]=-1;
        Xor[rt]=0;
    }
    if(Xor[rt]){
        fxor(rt<<1);
        fxor(rt<<1|1);
        Xor[rt]=0;
    }
}
void update(char op,int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R){
        if(op=='U'){
            cover[rt]=1;
            Xor[rt]=0;
        }
        if(op=='D'){
            Xor[rt]=cover[rt]=0;
        }
        if(op=='C'||op=='S'){
            fxor(rt);
        }
        return ;
    }
    push_down(rt);
    int m=(l+r)>>1;
    if(L<=m) update(op,L,R,lson);
    else if(op=='I'||op=='C'){
        Xor[rt<<1]=cover[rt<<1]=0;
    }
    if(m<R) update(op,L,R,rson);
    else if(op=='I'||op=='C'){
        Xor[rt<<1|1]=cover[rt<<1|1]=0;
    }

}
void query(int l,int r,int rt)
{
    if(cover[rt]==1){
        for(int it=l;it<=r;++it){
            hash[it]=true;
        }
        return;
    }else if(cover[rt]==0) return;
    push_down(rt);
    int m=(l+r)>>1;
    query(lson);
    query(rson);
}
int main()
{
    char op,l,r;int a,b;
    while(scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r)!=EOF){
        a<<=1,b<<=1;
        if(l=='(') a++;
        if(r==')') b--;
        if(a>b){
            if(op=='I'||op=='C'){
                Xor[1]=cover[1]=0;
            }
        }else{
            update(op,a,b,0,maxn,1);
        }
    }
    query(0,maxn,1);
    int s=-1,e;
    bool flag=false;
    for(int i=0;i<=maxn;++i){
        if(hash[i]){
            if(s==-1) s=i;
            e=i;
        }else{
            if(s!=-1){
                if(flag) printf(" ");
                flag=true;
                printf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']');
                s=-1;
            }
        }
    }
    if(!flag) printf("empty set\n");
    printf("\n");
    return 0;
}
时间: 2024-09-30 20:54:58

POJ 3225——Help with Intervals(线段树,成段替换+区间异或+hash)的相关文章

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

POJ 2528 Mayor&#39;s posters 线段树成段更新+离散化

题目来源:POJ 2528 Mayor's posters 题意:很多张海报贴在墙上 求可以看到几张海报 看那两张图就行了 第一张俯视图 思路:最多2W个不同的数 离散化一下 然后成段更新 a[rt] = i代表这个区间是第i张报纸 更新玩之后一次query cover[i]=1代表可以看到第i张报纸 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const

POJ训练计划2528_Mayor&#39;s posters(线段树/成段更新+离散化)

解题报告 地址传送门 题意: 一些海报,覆盖上去后还能看到几张. 思路: 第一道离散化的题. 离散化的意思就是区间压缩然后映射. 给你这么几个区间[1,300000],[3,5],[6,10],[4,9] 区间左右坐标排序完就是 1,3,4,5,6,9,10,300000; 1,2,3,4,5,6, 7 ,8; 我们可以把上面的区间映射成[1,8],[2,4],[5,7],[3,6]; 这样就节省了很多空间. 给线段染色, lz标记颜色. #include <map> #include <

POJ2528 Mayor&#39;s posters(线段树成段替换,区间查询,离散化简单hash)

题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报 思路:这题数据范围很大,直接搞超时+超内存,需要离散化: 离散化简单的来说就是只取我们需要的值来 用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要 1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了 所以离散化要保存所有需要用到的值,排序后,

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 3468 线段树 成段增减 区间求和

题意:Q是询问区间和,C是在区间内每个节点加上一个值 Sample Input 10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4Sample Output 455915 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6

HDU 3397 Sequence operation(线段树&#183;成段更新&#183;区间合并&#183;混合操作)

题意  给你一个只有0, 1的数组  有这些操作 0. 将[a, b]区间的所有数都改为0 1. 将[a, b]区间的所有数都改为1 2. 将[a, b]区间的所有数都取反 即与1异或 3. 输出区间[a, b]中1的个数  即所有数的和 4. 输出区间[a, b]中最大连续1的长度 对于所有的3, 4操作输出对应的答案 单个的操作都很简单  但搞在一起就有点恶心了  还好数组里的数只有0和1 线段树维护9个值 对应区间0, 1的最大长度len[i]  对应区间左端点为起点的最大0, 1长度ll

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