poj 3225 线段树之成段更新集合运算(交、并)

题目描述:

输入:        

U [1,5]

D [3,3]

S [2,4]

C (1,5)

I (2,3]

输出:

(2,3)

 

解题思路:

题意很明显,主要就是为了完成集合当中的并、交、差以及异或运算。

仔细分析一下题目这五种运算:设T左右区间分别为l,r

U T

将(l,r)当中的所有点都置为1

I T

保留l,r中1的位置,将(-∞,l)(r,+ ∞)置为0

D T

将(l,r)当中全部置为0

C T

将(l,r)当中0,1互换,将(-∞,l)(r,+ ∞)置为0

S T

将(l,r)当中0,1互换

至于开区间和闭区间的分别,可以用扩大总区间变为原来的两倍,用偶数来表示闭区间,基数来表示开区间。

其实这个线段树题,我觉得最难的还是在取反的过程当中,不过好好体会一下应该会很有收获的。

 

View Code
  1 #include<iostream>
  2 #include<stdio.h>
  3 #define lson t<<1,l,m
  4 #define rson t<<1|1,m+1,r
  5 using namespace std;
  6 const int N = 131071;
  7 int cover[N<<2];//覆盖 
  8 int Re[N<<2];//Re reserve 反向 
  9 int hash[N<<2];
 10 void Dir_back(int t)
 11 {
 12      if(cover[t]!=-1)cover[t]^=1;
 13      else Re[t]^=1;
 14 }
 15 void PushDown(int t)
 16 {
 17      if(cover[t]!=-1)
 18      {
 19         cover[t<<1]=cover[t<<1|1]=cover[t];
 20         Re[t<<1]=Re[t<<1|1]=0;
 21         cover[t]=-1;
 22      }
 23      if(Re[t])
 24      {         
 25         Dir_back(t<<1);
 26         Dir_back(t<<1|1);
 27         Re[t]=0;
 28      }
 29 }
 30 void update(int t,int l,int r,int L,int R,char o)
 31 {
 32      if(L<=l&&r<=R)
 33      {
 34         if(o=='U')cover[t]=1,Re[t]=0;
 35         else
 36            if(o=='D')cover[t]=0,Re[t]=0;
 37            else
 38               if(o=='C'||o=='S')
 39               Dir_back(t);
 40         return ;              
 41      }
 42      PushDown(t);
 43      int m=(l+r)>>1;
 44      if(L<=m)update(lson,L,R,o);
 45      else
 46      {
 47         if(o=='I'||o=='C')
 48         cover[t<<1]=Re[t<<1]=0;
 49      }
 50      if(R>m)update(rson,L,R,o);
 51      else
 52      {
 53         if(o=='I'||o=='C')
 54         cover[t<<1|1]=Re[t<<1|1]=0;
 55      }
 56 }
 57 void query(int t,int l,int r)
 58 {
 59      if(cover[t]==1)
 60      {
 61         for(int i=l;i<=r;i++)
 62         hash[i]=1;
 63         return ;               
 64      }
 65      else
 66        if(cover[t]==0)return ;
 67      if(l==r)return ;
 68      PushDown(t);
 69      int m=(l+r)>>1;
 70      query(lson);
 71      query(rson);
 72 }
 73 int main()
 74 {
 75     char o,l,r;
 76     int a,b;
 77     while(~scanf("%c %c%d,%d%c",&o,&l,&a,&b,&r))
 78     {
 79           getchar();
 80           a<<=1,b<<=1;
 81           if(l=='(')a++;
 82           if(r==')')b--;
 83           if(a>b)
 84           {
 85              if(o=='I'||o=='C')
 86              {
 87                 cover[1]=Re[1]=0;                  
 88              }       
 89           }
 90           else
 91           update(1,0,N,a,b,o);
 92     }
 93     query(1,0,N);
 94     int s=-1,e,flag=0;
 95     for(int i=0;i<=N;i++)
 96     {
 97         if(hash[i])
 98         {
 99            if(s==-1)s=i;
100            e=i;           
101         }
102         else
103         {
104            if(s!=-1)
105            {
106               if(flag)printf(" ");
107               flag=1;
108               printf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']');
109               s=-1;
110            }    
111         }
112     }
113     if(!flag)printf("empty set\n");
114     return 0;   
115 }

 

 

posted @ 2012-10-23 12:54  诺小J  阅读(226)  评论(0编辑  收藏  举报