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

Source

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


很久没做线段树了,拿来练手一脸懵逼。

这题坑点太多了,空集情况要考虑(这个坑了好久),边界要考虑(你以为是真无穷吗那不是药丸)

题解摘自kungbin博客:http://www.cnblogs.com/kuangbin/archive/2013/04/10/3012986.html

题意:给一个全局为0~65536的区间,一开始区间s为空间,然后不断地对区间s进行并上一个区间,交一个区间,减一个区间,用一个区间减去s,还有异或下两个区间。。。

题意:区间操作,交,并,补等
思路:
我们一个一个操作来分析:(用0和1表示是否包含区间,-1表示该区间内既有包含又有不包含)
U:把区间[l,r]覆盖成1
I:把[-∞,l)(r,∞]覆盖成0
D:把区间[l,r]覆盖成0
C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换
S:[l,r]区间0/1互换

分析:这题的各个操作都可以用线段树的成段更新在log(65536*2)的时间内完成

U:并上一个区间,也就是,将这个区间置1就行

I:交上一个区间[l,r],将区间[-∞,l)和(r,∞]置0

D:减去一个区间,将这个区间置0就行

C:用一个区间[l,r]减去s,将区间[-∞,l)和(r,∞]置0,区间[l,r]取反就行

S:求异或,区间[l,r]取反就行

现在上面的所有操作都在理论上解决掉了,而区间的开或闭这个直接把所有区间乘2,对于左边的开区间要加1,右边减1。

记得!空集!还有边界的0!MAXN!

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #define clr(x) memset(x,0,sizeof(x))
  5 const int MAXN=65536*2;
  6 using namespace std;
  7 struct segtree
  8 {
  9     int l,r,rev,val;// val==0表示全部没有覆盖,val==1表示全部被覆盖,其余为-1,rev==1表示取反,rev==0表示不变,只有val==-1时候rev才有作用
 10 }tree[MAXN*4+10];
 11 int cov[MAXN*2+10];
 12 void init(int l,int r,int i)//初始化
 13 {
 14     tree[i].l=l;
 15     tree[i].r=r;
 16     tree[i].rev=tree[i].val=0;
 17     if(l==r) return ;
 18     int mid=(l+r)>>1;
 19     init(l,mid,i<<1);
 20     init(mid+1,r,(i<<1)+1);
 21     return ;
 22 }
 23 void reverse(int i)//取反
 24 {
 25     if(tree[i].val!=-1) tree[i].val^=1;
 26     else
 27         tree[i].rev^=1;
 28  }
 29  void downto(int i)//向下更新
 30  {
 31      if(tree[i].val!=-1)
 32      {
 33          tree[i<<1].val=tree[(i<<1)+1].val=tree[i].val;
 34         tree[i].val=-1;
 35          tree[i<<1].rev=tree[(i<<1)+1].rev=0;
 36     }
 37     if(tree[i].rev)
 38     {
 39         reverse(i<<1);
 40         reverse((i<<1)+1);
 41         tree[i].rev=0;
 42     }
 43     return ;
 44  }
 45 void update(int i,int l,int r,int op)//操作更新区间
 46 {
 47     if(l<=tree[i].l && r>=tree[i].r)
 48     {
 49         if(op==0 || op==1)
 50         {
 51             tree[i].val=op;
 52             tree[i].rev=0;
 53         }
 54         else
 55             reverse(i);
 56         return;
 57     }
 58     downto(i);
 59     int mid=(tree[i].l+tree[i].r)>>1;
 60     if(r<=mid)
 61         update(i<<1,l,r,op);
 62     else
 63         if(l>mid)
 64             update((i<<1)+1,l,r,op);
 65         else
 66         {
 67             update((i<<1),l,r,op);
 68             update((i<<1)+1,l,r,op);
 69         }
 70     return ;
 71 }
 72 void query(int i)//标识出哪些区间存在,cov数组用来记录
 73 {
 74     if(tree[i].val==1)
 75     {
 76         for(int j=tree[i].l;j<=tree[i].r;j++)
 77             cov[j]=1;
 78         return ;
 79     }
 80     if(tree[i].val==0)
 81         return;
 82     if(tree[i].l==tree[i].r) return ;
 83     downto(i);
 84     query(i<<1);
 85     query((i<<1)+1);
 86     return ;
 87 }
 88 int main()
 89 {
 90     int lt,rt;
 91     char op,lc,rc;
 92     init(0,MAXN,1);
 93     while(scanf(" %c %c%d,%d%c",&op,&lc,&lt,&rt,&rc)!=EOF)
 94     {
 95         lt<<=1;
 96         if(lc==‘(‘)
 97             lt++;
 98         rt<<=1;
 99         if(rc==‘)‘)
100             rt--;
101         if(lt>rt)//空集情况!一定要注意
102         {
103             if(op==‘I‘ || op==‘C‘) update(1,0,MAXN,0);
104         }
105         else
106         {
107             if(op==‘U‘)
108             {
109                 update(1,lt,rt,1);
110             }
111             if(op==‘I‘)
112             {
113                 if(lt>0)update(1,0,lt-1,0);//注意边界lt>0 才能-1,rt也是如此。
114                 if(rt<MAXN)update(1,rt+1,MAXN,0);
115             }
116             if(op==‘D‘)
117             {
118                 update(1,lt,rt,0);
119             }
120             if(op==‘C‘)
121             {
122                 if(lt>0)update(1,0,lt-1,0);
123                 if(rt<MAXN)update(1,rt+1,MAXN,0);
124                 update(1,lt,rt,2);
125             }
126             if(op==‘S‘)
127             {
128                 update(1,lt,rt,2);
129             }
130         }
131     }
132     clr(cov);
133     query(1);
134     lt=0;
135     rt=-1;
136     for(int i=0;i<=MAXN;i++)
137     {
138         if(cov[i]==0 && cov[i+1]==1)
139         {
140             lt=i+1;
141         }
142         if(cov[i]==1 && cov[i+1]==0)
143         {
144             rt=i;
145             if(lt%2==1)
146                 printf("(%d,",lt/2);
147             else
148                 printf("[%d,",lt/2);
149             if(rt%2==1)
150                 printf("%d) ",rt/2+1);
151             else
152                 printf("%d] ",rt/2);
153         }
154     }
155     if(lt>rt)
156     {
157         printf("empty set\n");
158     }
159     else
160         printf("\n");
161     return 0;
162 }
时间: 2024-08-06 07:58:27

poj 3225 Help with Intervals(线段树,区间更新)的相关文章

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 2528 Mayor&#39;s posters 线段树区间更新

Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at al

poj 2777 Count Color (线段树区间更新)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37647   Accepted: 11315 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.

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 , 线段树+集合。

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 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 2777 Count Color(线段树区间修改)

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

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac