POJ 3225

题意:定义对集合的交、并、差、异或,求空集经过一系列操作后的结果。

题解:将原点集每一个点乘以2,形成一个新的点集,其中偶数点都对应着原来的点,奇数点对应着不包括它左右两个点的开区间,即2k+1==>(k,k+1),于是区间上所有点都能用整点表示,线段树可求解,对于每一个操作区间,无论开闭,都对应这线段树上的一段线段。

1、并运算[a,b],就是将[a,b]赋值为1.(a,b均为对应之后的点)

2、交运算[a,b],将除了[a,b]区间以外的线段清0.

3、S-[a,b],将[a,b]区间清0.

4、[a,b]-S,将[a,b]区间以外线段清0,并且将[a,b]线段所代表区域取反.

5、异或运算,上面两者去并,就是将[a,b]区域取反.

View Code
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cctype>
  5 using namespace std;
  6 const int maxn=66000*2;
  7 const int N=maxn*4;
  8 struct Line
  9 {
 10     int left,right;
 11     int tag;
 12     bool rev;
 13 } line[N];
 14 void build(int now,int left,int right)
 15 {
 16     line[now].left=left;
 17     line[now].right=right;
 18     line[now].tag=0;
 19     line[now].rev=false;
 20     if(left==right)
 21         return;
 22     int mid=(left+right)>>1;
 23     build(now*2,left,mid);
 24     build(now*2+1,mid+1,right);
 25 }
 26 void pushdown(int now)
 27 {
 28     if(line[now].left==line[now].right)
 29     {
 30         if(line[now].rev)
 31         {
 32             line[now].tag^=1;
 33             line[now].rev=false;
 34         }
 35         return;
 36     }
 37     if(line[now].tag!=-1)
 38     {
 39         if(line[now].rev)
 40             line[now].tag^=1;
 41         line[now*2].tag=line[now*2+1].tag=line[now].tag;
 42         line[now].tag=-1;
 43         line[now].rev=line[now*2].rev=line[now*2+1].rev=false;
 44     }
 45     if(line[now].rev)
 46     {
 47         line[now].rev=false;
 48         if(line[now*2].tag==-1)
 49             line[now*2].rev^=true;
 50         else
 51             line[now*2].tag^=1;
 52         if(line[now*2+1].tag==-1)
 53             line[now*2+1].rev^=true;
 54         else
 55             line[now*2+1].tag^=1;
 56     }
 57 }
 58 void solve(int now,int left,int right,int op)
 59 {
 60     if(left>right)
 61         return;
 62     int ll=line[now].left,rr=line[now].right;
 63     if(ll==left&&rr==right)
 64     {
 65         if(op<2)
 66         {
 67             line[now].rev=false;
 68             line[now].tag=op;
 69         }
 70         else if(line[now].tag!=-1)
 71         {
 72             line[now].tag^=1;
 73         }
 74         else
 75         {
 76             line[now].rev^=1;
 77         }
 78         return;
 79     }
 80     int mid=(ll+rr)>>1;
 81     pushdown(now);
 82     if(mid<left)
 83     {
 84         solve(now*2+1,left,right,op);
 85     }
 86     else if(right<=mid)
 87     {
 88         solve(now*2,left,right,op);
 89     }
 90     else
 91     {
 92         solve(now*2,left,mid,op);
 93         solve(now*2+1,mid+1,right,op);
 94     }
 95 }
 96 bool vis[N];
 97 void findinter(int now)
 98 {
 99     if(line[now].tag!=-1)
100     {
101         if(line[now].tag==1)
102         {
103             int ll=line[now].left,rr=line[now].right;
104             for(int i=ll; i<=rr; i++)
105                 vis[i]=true;
106         }
107         return;
108     }
109     pushdown(now);
110     findinter(now*2);
111     findinter(now*2+1);
112 }
113 int main()
114 {
115     build(1,0,maxn);
116     char s[100];
117     while(gets(s))
118     {
119         int len=strlen(s),i,op,a=0,b=0;
120         for(i=3;i<len;i++)
121         {
122             if(!isdigit(s[i]))
123                 break;
124             a=a*10+s[i]-'0';
125         }
126         for(i++;i<len;i++)
127         {
128             if(!isdigit(s[i]))
129                 break;
130             b=b*10+s[i]-'0';
131         }
132         if(s[i]==']')
133             b=b*2;
134         else
135             b=b*2-1;
136         if(s[2]=='[')
137             a=a*2;
138         else
139             a=a*2+1;
140         switch(s[0])
141         {
142             case 'U':solve(1,a,b,1);break;
143             case 'I':solve(1,0,a-1,0);solve(1,b+1,maxn,0);break;
144             case 'D':solve(1,a,b,0);break;
145             case 'C':solve(1,0,a-1,0);solve(1,b+1,maxn,0);solve(1,a,b,2);break;
146             case 'S':solve(1,a,b,2);break;
147         }
148     }
149     memset(vis,false,sizeof(vis));
150     findinter(1);
151     bool first=true;
152     for(int i=0; i<=maxn; i++)
153     {
154         if(!vis[i])
155             continue;
156         int a=i,b;
157         while(vis[i]&&i<=maxn)
158             i++;
159         b=--i;
160         if(first)
161             first=false;
162         else
163             printf(" ");
164         if(a&1)
165             printf("(%d,",a/2);
166         else
167             printf("[%d,",a/2);
168         if(b&1)
169             printf("%d)",(b+1)/2);
170         else
171             printf("%d]",b/2);
172     }
173     if(first)
174         printf("empty set");
175     printf("\n");
176     return 0;
177 }

转载于:https://www.cnblogs.com/tmeteorj/archive/2012/09/21/2697507.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值