您的位置:首页 > 其它

POJ 3225 Help with Intervals(线段树成段更新)

2013-09-22 16:22 447 查看
Help with Intervals

Time Limit: 6000MSMemory Limit: 131072K
Total Submissions: 8851Accepted: 2103
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:



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:



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] (a, b ∈ 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)

Source

PKU Local 2007 (POJ Monthly--2007.04.28), frkstyc

题意:

1.起初给你一个空区间,给你一些集合的运算符号和操作数。

2.具体的集合运算符号有并、交、相对补和对称差,如下图:



这道题在POJ上有简体中文版的~~



3.最后输出经过这一系列操作后的集合,若集合为空,输出“
empty set
”。

思路:

1.将这一系列数学符号转化成简单的执行操作,即如下:

U [l,r]:把区间[l,r]覆盖成1

I [l,r]:把区间[-∞,l)(r,∞]覆盖成0

D [l,r]:把区间[l,r]覆盖成0

C [l,r]:把区间[-∞,l)(r,∞]覆盖成0 , 且区间[l,r]内0/1互换

S [l,r]:把区间[l,r]内0/1互换

2.成段覆盖操作类似于染色,注意点是需要在每次update和query时的down一下。

3.区间内0/1互换即区间内的异或操作,如下:

1)若某次操作是将一段区间覆盖的话,那么之前的异或操作都没有了意义,区间覆盖时需要把异或标记清零。

2)若某次操作是将一段区间异或的话,需要判断:若这段区间覆盖标记为0或1,只需将覆盖标记改变一下,若不是的话,需要改变异或标记

4.区间的开闭问题,可以将区间的左右端点乘以2来考虑。举几个易懂的例子,如下

[2,3] --> [4,6]

[2,3) --> [4,5]

(2,3] --> [5,6]

(2,3) --> [5,5]

(3,3) --> [7,5] 这点需要注意!

/*************************************************************************
> File Name: poj3225.cpp
> Author: BSlin
> Mail:
> Created Time: 2013年09月21日 星期六 22时19分37秒
************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iterator>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#define MP make_pair
#define INF (1<<30)
#define PI acos(-1.0)
#define esp 1e-8
const int dx[4]={0,0,0,0};
using namespace std;
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#if defined (_WIN32) || defined (__WIN32) || defined (WIN32) || defined (__WIN32__)
#define LL __int64
#define LLS "%" "I" "6" "4" "d"
#else
#define LL long long
#define LLS "%" "l" "l" "d"
#endif

#define MAX 131080

struct node {
int L,R,cover,turn;
}tree[MAX<<2];

bool hash[MAX];

void build( int L, int R, int p ) {
tree[p].L = L;
tree[p].R = R;
tree[p].cover = 0;
tree[p].turn = 0;
if(L == R) return ;
int mid = (L + R) >> 1;
build(L, mid, p<<1);
build(mid+1, R, p<<1|1);
}

void change( int p ) {
if(tree[p].cover != -1) {
tree[p].cover ^= 1;
}
else tree[p].turn ^= 1;
}

void down(int p) {
if( tree[p].cover != -1 ){
tree[p<<1].cover = tree[p<<1|1].cover =tree[p].cover;
tree[p<<1].turn = tree[p<<1|1].turn = 0;
tree[p].cover = -1;
}
if(tree[p].turn) {
change( p<<1 );
change( p<<1|1 );
tree[p].turn = 0;
}
}

void update( char op, int L, int R, int p ) {
if( L <= tree[p].L && tree[p].R <= R ) {
if( op == 'U' ) {
tree[p].cover = 1;
tree[p].turn = 0;    //一开始忘加了
}
else if( op == 'D' ) {
tree[p].cover = 0;
tree[p].turn = 0;    //一开始忘加了
}
else if( op == 'C' || op == 'S' ) {
change(p);
}
return ;
}
down(p);
int mid = ( tree[p].L + tree[p].R ) >> 1;
if( R <= mid ) {
if( op == 'I' || op == 'C' ) {
tree[p<<1|1].cover = tree[p<<1|1].turn = 0;
}
update( op, L, R, p<<1 );
}
else if( L > mid ) {
if( op == 'I' || op == 'C' ) {
tree[p<<1].cover = tree[p<<1].turn = 0;
}
update( op, L, R, p<<1|1 );
}
else {
update( op, L, mid, p<<1 );
update( op, mid+1, R, p<<1|1 );
}

}

void query( int p ) {
if( tree[p].cover == 1 ) {
for( int i=tree[p].L; i<=tree[p].R; i++ ) {
hash[i] = 1;
}
return ;
}
else if( tree[p].cover == 0 ) return ;
down(p);
query( p<<1 );
query( p<<1|1 );
}

int main(int argc, char** argv) {
//read;
int a,b,start,end;
bool flag;
char op,c1,c2;
build(0,MAX,1);
memset( hash, 0, sizeof(hash) );
while( scanf( "%c %c%d,%d%c\n",&op, &c1, &a, &b, &c2 ) != EOF ) {
a = a << 1;
b = b << 1;
if(c1 == '(') a++;
if(c2 == ')') b--;
if( a > b ) {           //注意,例如(3,3);
if( op == 'I' || op == 'C' ) {
tree[1].cover = tree[1].turn = 0;
}
}
else update( op, a, b, 1 );
}
query(1);
start = -1;
flag = false;
for( int i=0; i<=MAX; i++ ) {
if(hash[i]) {
if(start == -1) start = i;
end = i;
}
else {
if(start != -1) {
if( flag ) printf(" ");
flag = true;
if( start % 2 ) printf("(%d,", start>>1);
else printf("[%d,",start>>1);
if( end % 2 ) printf("%d)", (end+1)>>1);
else printf("%d]", (end+1)>>1);
start = -1;
}
}
}
if( flag == 0 ) printf( "empty set" );
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: