ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

POJ - 3225 Help with Intervals (区间置0/1与区间异或混合操作)

2019-07-15 11:38:25  阅读:252  来源: 互联网

标签:Help lazyXor 3225 mid ul 区间 type define


Help with Intervals

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 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)

题意:让模拟并、交、相对补、对称差。每一次都给定一个区间和操作类型,问最后区间是什么样子,用并的方式输出

思路:首先是括号'[' 和 '(' 的问题,这表明更新时 是更新一个区间,而不是区间上的端点,所以需要新插入一个点代表两点之前的段。 由于点是从 0 开始的,我采用的操作是  如端点 l , 先 ++ l,然后以 2 * l - 1 作为线段树的更新端点,这样原每两个相邻的点之间就会插入一个点。

  • 并:直接将 更新区间置1
  • 交:将更新区间的两边置0
  • 相对补:两边置0,更新区间所有值取异或
  • 对称差:更新区间所有值取异或

我一开始,只设置了一个 type 数组,表示区间是否是同一值。利用 type 直接更新到值相同的段,然后 T 了。

搜了一下题解,还需要用到 lazyXor 数组。

唯一 一个需要很理解的地方就是:如果当前区间是同一值,就对 type 数组操作 (因为最后查询的时候是查询 type 是否为 1),否则就只能对 lazyXor 操作。   对于 push_down 时,type 的优先级要大于 lazyXor,也就是 如果能够利用 type 进行push_down,就用type,同时还要将两个儿子的 lazyXor 置0 (因为这是直接赋值的,且type != -1 时,这个区间的 lazyXor 一定为 0)。置 0/1 时也要将 lazyXor 置0

贴上抄袭代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#pragma GCC optimize(2)
#define INT(t) int t; scanf("%d",&t)

using namespace std;

const int maxn = 65536 * 2 + 10;
int type[maxn << 2];
int lazyXor[maxn << 2];
const int n = 65536 * 2 - 1;

void solve(int i){
    if(type[i] != -1){
        type[i] ^= 1;
        lazyXor[i] = 0;
    }
    else lazyXor[i] ^= 1;
}

void push_down(int l,int r,int i){
    if(type[i] != -1){
        type[ls] = type[rs] = type[i];
        lazyXor[ls] = lazyXor[rs] = 0;
        type[i] = -1;
    }
    else if(lazyXor[i] == 1){
        solve(ls);
        solve(rs);
        lazyXor[i] = 0;
    }
}

void update(int l,int r,int ul,int ur,int i,int UorI){
    if(ul > ur) return ;
    if(ul <= l && r <= ur){
        type[i] = UorI;
        lazyXor[i] = 0;
        return ;
    }
    push_down(l,r,i);
    int mid = (l + r) >> 1;
    if(ul <= mid) update(l,mid,ul,ur,i << 1,UorI);
    if(ur > mid) update(mid + 1,r,ul,ur,i << 1 | 1,UorI);
    type[i] = (type[i << 1] == type[i << 1 | 1] ? type[i << 1] : -1);
}

void updateC(int l,int r,int ul,int ur,int i){
    if(ul > ur) return ;
    if(ul <= l && r <= ur){
        solve(i);
        return ;
    }
    if(l == r) return ;
    push_down(l,r,i);
    int mid = (l + r) >> 1;
    if(ul <= mid) updateC(l,mid,ul,ur,i << 1);
    if(ur > mid) updateC(mid + 1,r,ul,ur,i << 1 | 1);

}

#define ok(x) (2 * (x) - 1)

bool query(int l,int r,int pos,int i){
    if(l == r)
        return type[i] == 1;
    push_down(l,r,i);
    int mid = (l + r) >> 1;
    if(pos <= mid) return query(l,mid,pos,i << 1);
    if(pos > mid) return query(mid + 1,r,pos,i << 1 | 1);
}

int main() {
    char ch;
    while(~scanf("%c",&ch)){
        char lef,rig;
        int l,r;
        scanf(" %c%d,%d%c",&lef,&l,&r,&rig);
        ++ l; ++ r;
        l = ok(l);
        r = ok(r);
        if(ch == 'U'){
            if(lef == '(') ++ l;
            if(rig == ')') -- r;
            update(1,n,l,r,1,1);/// 把中间的直接变成1
        }
        else if(ch == 'I'){     /// 把两边的全部变成0
            if(lef == '[') -- l;
            if(rig == ']') ++ r;
            update(1,n,1,l,1,0);
            update(1,n,r,n,1,0);
        }
        else if(ch == 'D'){
            if(lef == '(') ++ l;
            if(rig == ')') -- r;
            update(1,n,l,r,1,0);
        }
        else if(ch == 'C'){
            if(lef == '[') -- l;
            if(rig == ']') ++ r;
            update(1,n,1,l,1,0);
            update(1,n,r,n,1,0);
            ++ l;
            -- r;
            updateC(1,n,l,r,1);
        }
        else {
            if(lef == '(') ++ l;
            if(rig == ')') -- r;
            updateC(1,n,l,r,1);
        }
        getchar();
    }
    int coun = 0;
        int Beg = maxn,END;
        char Lef,Rig;
        for(register int i = 1;i <= n + 1;++ i){
            int tttmp = i == n + 1 ? 0 : query(1,n,i,1);
            if(tttmp){
                END = (i + 1) / 2 - 1;
                Rig = i % 2 == 1 ? ']':')';
                if(Beg > END){
                    Beg = END;
                    Lef = i % 2 == 1 ? '[':'(';
                }
                ++ coun;
            }
            else if(!tttmp || i == n + 1){
                if(coun && Beg != maxn) printf("%c%d,%d%c ",Lef,Beg,END + (i % 2 == 1),Rig);
                Beg = maxn;
            }
        }
        if(coun == 0) printf("empty set");
        printf("\n");
    return 0;
}

 

标签:Help,lazyXor,3225,mid,ul,区间,type,define
来源: https://blog.csdn.net/no_O_ac/article/details/95945416

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有