POJ 3225(线段树)

POJ 3225

题 意 : 区 间 操 作 , 交 , 并 , 补 等

思 路 :

  我 们 一 个 一 个 操 作 来 分 析 :( 用 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 互 换

    成 段 覆 盖 的 操 作 很 简 单 , 比 较 特 殊 的 就 是 区 间 0 / 1 互 换 这 个 操 作 , 我 们 可 以 称 之 为 异或 操 作

    很 明 显 我 们 可 以 知 道 这 个 性 质 : 当 一 个 区 间 被 覆 盖 后 , 不 管 之 前 有 没 有 异 或 标 记 都 没有 意 义 了

    所 以 当 一 个 节 点 得 到 覆 盖 标 记 时 把 异 或 标 记 清 空
    而 当 一 个 节 点 得 到 异 或 标 记 的 时 候 , 先 判 断 覆 盖 标 记 , 如 果 是 0 或 1 , 直 接 改 变 一 下 覆盖 标 记 ,

  不 然 的 话 改 变 异 或 标 记

    开 区 间 闭 区 间 只 要 数 字 乘 以 2 就 可 以 处 理 ( 偶 数 表 示 端 点 , 奇 数 表 示 两 端 点 间 的 区 间 ) 线 段 树 功 能 :

  u p d a t e : 成 段 替 换 ,区 间 异 或 q u e r y : 简 单 h a s h

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define lson l,m,rt<<1
 5 #define rson m+1,r,rt<<1|1
 6 using namespace std;
 7 const int MAX = 65555*2;
 8 bool Hash[MAX];
 9 int cover[MAX<<2], XOR[MAX<<2];
10 void FXOR(int rt){
11     if(cover[rt] != -1)cover[rt]^=1;
12     else XOR[rt] ^= 1;
13 }
14 void PushDown(int rt){
15     if(cover[rt] != -1){
16         cover[rt<<1] = cover[rt<<1|1] = cover[rt];
17         XOR[rt<<1] = XOR[rt<<1|1] = 0;
18         cover[rt] = -1;
19     }
20     if(XOR[rt]){
21         FXOR(rt<<1);
22         FXOR(rt<<1|1);
23         XOR[rt] = 0;
24     }
25 }
26 void update(char op, int LL, int RR, int l, int r, int rt){
27     if(LL <= l && r <= RR){
28         if(op == ‘U‘){
29             cover[rt] = 1;
30             XOR[rt] = 0;
31         }else if(op == ‘D‘){
32             cover[rt] = 0;
33             XOR[rt] = 0;
34         }else if(op == ‘C‘ || op == ‘S‘){
35             FXOR(rt);
36         }
37         return;
38     }
39     PushDown(rt);
40     int m = (l+r)>>1;
41     if(LL <= m)update(op,LL,RR,lson);
42     else if(op == ‘I‘ || op == ‘C‘){
43         XOR[rt<<1] = cover[rt<<1] = 0;
44     }
45     if(m < RR)update(op,LL,RR,rson);
46     else if(op == ‘I‘ || op == ‘C‘){
47         XOR[rt<<1|1] = cover[rt<<1|1] = 0;
48     }
49 }
50 void query(int l, int r, int rt){
51     if(cover[rt] == 1){
52         for(int it = l; it <= r; it++){
53             Hash[it] = true;
54         }
55         return;
56     }else if(cover[rt] == 0)return;
57     if(l == r) return;
58     PushDown(rt);
59     int m = (l+r)>>1;
60     query(lson);
61     query(rson);
62 }
63 int main(){
64     cover[1] = XOR[1] = 0;
65     char op, l, r;
66     int a, b;
67     while(~scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r)){
68         a<<=1, b<<=1;
69         if(l == ‘(‘)a++;
70         if(r == ‘)‘)b--;
71         if(a > b){
72             if(op==‘C‘ || op == ‘I‘){
73                 cover[1] = XOR[1] = 0;
74             }
75         }else update(op,a,b,0,MAX,1);
76     }
77     query(0,MAX,1);
78     bool flag = false;
79     int s = -1,e;
80     for(int i = 0; i <= MAX; i ++){
81         if(Hash[i]){
82             if(s == -1)s=i;
83             e =i;
84         }else{
85             if(s != -1){
86                 if(flag)printf(" ");
87                 flag = true;
88                 printf("%c%d,%d%c",s&1?‘(‘:‘[‘,s>>1,(e+1)>>1,e&1?‘)‘:‘]‘);
89                 s=-1;
90             }
91         }
92     }
93     if(!flag)printf("empty set");
94     return 0;
95 }
时间: 2024-12-17 16:31:55

POJ 3225(线段树)的相关文章

poj 3225 线段树+位运算

略复杂的一道题,首先要处理开闭区间问题,扩大两倍即可,注意输入最后要\n,初始化不能随便memset 采用线段树,对线段区间进行0,1标记表示该区间是否包含在s内U T S ← S ∪ T 即将[l,r]标记为1I T S ← S ∩ T 即将-oo~l和r~+oo标记为0,因为是并集,所以并集后的集合s一定在[l,r]内,则在l,r内的集合被标记是什么状态就是什么状态(表示是否属于s),[l,r]外的集合不属于s所以标记为0D T S ← S - T  即将[l,r]标记为0,则在[l,r]内

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

这道题搞了好久,其实坑点挺多.. 网上找了许多题解,发现思路其实都差不多,所以就不在重复了. 推荐一篇比较好的题解,请戳这. 另外,如果因为可能要更新多次,但最终查询只需要一次,所以没有写pushup函数,仅有一个pushdown. 1 #include <cstdio> 2 3 const int maxn = 131072; 4 //const int maxn = 10; 5 int qL, qR, op; 6 int setv[maxn << 2], xorv[maxn &

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

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj 2777 线段树的区间更新

Count Color Time Limit: 1000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Chosen Problem Solving and Program design as an optional course, you are required to solve al

转载::POJ 2991 线段树+计算几何(有c++结构体操作)

POJ 2991 线段树+计算几何 (2011-02-27 21:13:44) 转载▼ 标签: 杂谈 分类: OI 话说这一题真的是很恶心很恶心,不过确实改变了我对线段树的一些看法,算是很经典的题目. 题意:有一个吊车由很多个不同长度的线段组成,一开始是一条长直线起点在(0,0),尾节点在(0,sum[n]),每条线段之间的夹角的初始值是180度.然后有一些操作a. b将第a条线段和a+1之间的夹角变成b度,经过每一次操作都要求出尾节点的坐标. 首先要用到一个计算几何的知识(没学过..请教而来)

poj 2750(线段树的动态规划)

Potted Flower Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4186   Accepted: 1581 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrounded by N pots of f

POJ 2570 线段树

Potted Flower Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description The little cat takes over the management of a new park. There is a large circular statue in

poj 2828 线段树

http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 并且后来的也可以确定----如果从前往后,所有的随时都不是确定的 2.线段树叶子节点直接维护区间(线段)信息,非叶子节点v维护的是以v为树根的整个子树的信息,那么假设父节点rt信息为[l,r]那么左子树维护[l,mid],右子树维护[mid+1,r]的信息.如果如果是前缀和,rt里是1-n的和,左子树1~n/2的和,右子树是n/2+1~n

POJ 3468 线段树+lazy标记

lazy标记 Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to