poj 3225 Help with Intervals(过题啦啦~)

来源:互联网 发布:ubuntu 安装出错 编辑:程序博客网 时间:2024/05/18 14:45

这个题是线段树经典题目,相信学过线段树的童鞋一定见过。。

我之前一直木有做,没仔细看,觉得应该不算太难,但是懒得做。。

前天一ACMer跟我聊线段树,谈到一种情况,就是线段和点同时有意义的时候,我当时就想,那扩大二倍应该就没啥问题了,然后他就说到这个题了。。。然后我决定做一下~

sha崽大牛线段树上面有这个题,可以把并交差与区间覆盖异或联系起来,引用下。具体地:

如果以1代表当前有值的话,那么假设T的区间为l,r,开闭先不管。。

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互换

注意区间开闭的判断。

最后找连续的区间即可。

具体的我的代码有注释。。。难得我写一次注释。。嘿嘿。。代码很长。。。我觉得我缩不了了。。。><。。。

#include <set>#include <map>#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define BUG puts("here!!!")#define STOP system("pause")#define file_r(x) freopen(x, "r", stdin)#define file_w(x) freopen(x, "w", stdout)using namespace std;const int MAX = 70000*2;bool a[MAX<<2];struct Tnode{// 一维线段树     int l,r,cover;    bool x;    int len() { return r - l;}    int mid() { return MID(l,r);}    bool in(int ll,int rr) { return l >= ll && r <= rr; }    void lr(int ll,int rr){ l = ll; r = rr;}};Tnode node[MAX<<2];void Build(int t,int l,int r){node[t].x = false;//x 为 false 代表不异或 node[t].cover = 0;//  cover为-1代表当前区间有0有1, 初始化为空集合 node[t].lr(l,r);if( node[t].len() == 1 ) return ;int mid = MID(l,r);Build(L(t),l,mid);Build(R(t),mid,r);}void Updata_x(int t)// 向下更新异或,因为cover在上一条命令结束时已经更新过了 {// 保证异或标记为真,那么cover必然等于-1 if( node[t].len() == 1 ){if( node[t].x ){node[t].x = false;node[t].cover = node[t].cover ^ 1;}return ;}if( node[t].cover != -1 ){node[L(t)].cover = node[R(t)].cover = node[t].cover;node[L(t)].x = node[R(t)].x = false;}else{if( node[t].x ){node[L(t)].x = !node[L(t)].x;node[R(t)].x = !node[R(t)].x;if( node[L(t)].cover != -1 && node[L(t)].x ){node[L(t)].x = false;node[L(t)].cover = node[L(t)].cover ^ 1;}if( node[R(t)].cover != -1 && node[R(t)].x ){node[R(t)].x = false;node[R(t)].cover = node[R(t)].cover ^ 1;}node[t].x = false;}}}void Updata_cover(int t)// 更新父节点cover {if( node[L(t)].cover == node[R(t)].cover )node[t].cover = node[L(t)].cover;elsenode[t].cover = -1;}void Updata(int t, int l, int r, int op, int val){if( l >= r || l < 0 ) return ;//防止出现一些非法状况 Updata_x(t);if( node[t].in(l,r) ){if( op == 0 )// 覆盖操作,把异或标记清空 {node[t].cover = val;node[t].x = 0;}else{if( node[t].cover != -1 )node[t].cover = node[t].cover ^ 1;// 当前区间被覆盖,更改cover的值 elsenode[t].x = !node[t].x;// 当前区间 有0有1 }                          return ;}if( node[t].len() == 1 ) return ;int mid = node[t].mid();if( l < mid ) Updata(L(t), l, r, op, val);if( r > mid ) Updata(R(t), l, r, op, val);Updata_cover(t);}void Query(int t){Updata_x(t);if( node[t].len() == 1 ){ a[ node[t].l ] = ( node[t].cover ? true : false ); return ;}Query(L(t));Query(R(t));}void solve(char op, char l, char r, int x, int y){int lb, lk, rb, rk, ll, rr;lb = 2*x;lk = 2*x + 1;//左闭 左开 rb = 2*y + 1; rk = 2*y;//右闭 右开 ll = ( l == '(' ? lk : lb );rr = ( r == ')' ? rk : rb ); switch( op ){case 'U':Updata(1, ll, rr, 0, 1);break;case 'I':Updata(1, 0, ll, 0, 0);Updata(1, rr, MAX, 0, 0);break;case 'D':Updata(1, ll, rr, 0, 0);break;case 'C':Updata(1, ll, rr, 1, 0);Updata(1, 0, ll, 0, 0);Updata(1, rr, MAX, 0, 0);break;case 'S':Updata(1, ll, rr, 1, 0);}}void output(){int cnt = 0;Query(1);FOR(i, 0, MAX*2){if( a[i] && cnt % 2 == 0 ){if( cnt != 0 )printf(" ");printf( i % 2 == 1 ? "(%d," : "[%d,", i/2);cnt++;}if( !a[i] && cnt % 2 == 1 ){printf( i % 2 == 1 ? "%d]" : "%d)", i/2);cnt++;}}if( cnt == 0 )printf("empty set");printf("\n");}/*左闭  2*x左开  2*x + 1右闭  2*y + 1右开  2*y*/ int main(){char op[5], s[100], l, r;int x, y;memset(a, false, sizeof(a));Build(1, 0, MAX);while( ~scanf("%s%s", op, s) ){sscanf(s, "%c%d,%d%c", &l, &x, &y, &r);solve(op[0], l, r, x, y);}output();return 0;}


原创粉丝点击