首页 > 代码库 > POJ 3225(线段树)

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 }

 

POJ 3225(线段树)