码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3225 线段树+位运算

时间:2015-02-10 13:03:13      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:

略复杂的一道题,首先要处理开闭区间问题,扩大两倍即可,注意输入最后要\n,初始化不能随便memset

采用线段树,对线段区间进行0,1标记表示该区间是否包含在s内
U T S ← S ∪ T 即将[l,r]标记为1
I T S ← S ∩ T 即将-oo~l和r~+oo标记为0,因为是并集,所以并集后的集合s一定在[l,r]内,则在l,r内的集合被标记是什么状态就是什么状态(表示是否属于s),[l,r]外的集合不属于s所以标记为0
D T S ← S - T  即将[l,r]标记为0,则在[l,r]内被s包含的集合也会标记为0表示不再属于s
C T S ← T - S  即先将-oo~l,r~+oo标记为0,这部分不属于[l,r]则一定不属于s,然后将[l,r]的标记0/1互换,因为属于s的不再属于s,不属于s的将属于s
S T S ← S ⊕ T  即属于s的不变,[l,r]中不属于s的(区间)0标记为1,属于s的(区间)1标记为0,所以[l,r]的标记0/1互换

最后对区间l,r标记时标记将l*2,r*2标记,如果是闭区间则对l*2+1,或r*2-1进行标记,则输出的时候只需判断奇偶就能判断开闭区间
是否覆盖0,1是否转换0,1的0,1转换都可以用异或去转换
Sample Input
U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]
Sample Output
(2,3)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #define lson l,m,rt<<1
  8 #define rson m+1,r,rt<<1|1
  9 using namespace std;
 10 const int maxn=131072;
 11 int tot=0;
 12 int n,m,t;
 13 int Xor[maxn<<2],cov[maxn<<2];   //异或标记,覆盖标记
 14 int hash[maxn<<2];
 15 void XXor(int rt)
 16 {
 17     if(cov[rt]!=-1) cov[rt]^=1;     //说明该区域有值存在
 18     else Xor[rt]^=1;
 19 }
 20 void pushdown(int rt)
 21 {
 22     if(cov[rt]!=-1)
 23     {
 24         cov[rt<<1]=cov[rt<<1|1]=cov[rt];
 25         Xor[rt<<1]=Xor[rt<<1|1]=0;
 26         cov[rt]=-1;
 27     }
 28     if(Xor[rt])
 29     {
 30         XXor(rt<<1);
 31         XXor(rt<<1|1);
 32         Xor[rt]=0;
 33     }
 34 }
 35 void update(char op,int L,int R,int l,int r,int rt)
 36 {
 37     if(l>=L&&r<=R)
 38     {
 39 
 40         if(op==U) cov[rt]=1,Xor[rt]=0;
 41         else if(op==D)    cov[rt]=Xor[rt]=0;
 42         else if(op==C||op==S)   XXor(rt);
 43         return;
 44     }
 45     pushdown(rt);
 46     int m=(l+r)>>1;
 47     if(L<=m) update(op,L,R,lson);
 48     else if(op==I||op==C)   cov[rt<<1]=Xor[rt<<1]=0;
 49     if(m<R) update(op,L,R,rson);
 50     else if(op==I||op==C)   cov[rt<<1|1]=Xor[rt<<1|1]=0;
 51 }
 52 void query(int l,int r,int rt)
 53 {
 54     if(cov[rt]==1)
 55     {
 56         for(int i=l;i<=r;i++)   hash[i]=1;
 57         return;
 58     }
 59     else if(cov[rt]==0) return;
 60     if(l==r)    return;
 61     pushdown(rt);
 62     int m=(r+l)>>1;
 63     query(lson);
 64     query(rson);
 65 }
 66 int main()
 67 {
 68     int i,j,k;
 69     //freopen("1.in","r",stdin);
 70     char l,r,op;
 71     int a,b;
 72     while(scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r)!=EOF)
 73     {
 74         a<<=1,b<<=1;    //区间扩大一倍,解决开闭区间问题
 75         //printf("%d %d\n",a,b);
 76         if(l==()  a++;
 77         if(r==))  b--;
 78         if(a>b)         //说明a和b的值相等
 79         {
 80             if(op==C||op==I)    cov[1]=Xor[1]=0,printf("");    //整个区间为0
 81         }
 82         else    update(op,a,b,0,maxn,1);
 83     }
 84     k=0;
 85     query(0,maxn,1);    //此时区间内的有效区域值为1
 86     int s=-1,e;    //判断左右区间位置
 87 
 88     for(i=0;i<=maxn;i++)
 89     {
 90         if(hash[i]) //该区域被覆盖
 91         {
 92             if(s==-1)   s=i;
 93             e=i;
 94         }
 95         else
 96         {
 97             if(s!=-1)    //说明存在一个完整区间
 98             {
 99                 if(k++) printf(" ");
100                 printf("%c%d,%d%c",s&1?(:[,s>>1,(e+1)>>1,e&1?):]);    //&运算用来判断奇偶,偶数的话二进制末位为0,and1得0,说明为闭区间
101                 s=-1;
102             }
103         }
104     }
105     if(k==0)    printf("empty set");
106     puts("");
107     return 0;
108 }

 

poj 3225 线段树+位运算

标签:

原文地址:http://www.cnblogs.com/cnblogs321114287/p/4283369.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!