poj 3225 Help with Intervals(过题啦啦~)
2011-09-27 14:07
375 查看
这个题是线段树经典题目,相信学过线段树的童鞋一定见过。。
我之前一直木有做,没仔细看,觉得应该不算太难,但是懒得做。。
前天一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互换
注意区间开闭的判断。
最后找连续的区间即可。
具体的我的代码有注释。。。难得我写一次注释。。嘿嘿。。代码很长。。。我觉得我缩不了了。。。><。。。
我之前一直木有做,没仔细看,觉得应该不算太难,但是懒得做。。
前天一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; else node[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的值 else node[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; }
相关文章推荐
- POJ 3225 Help with Intervals
- POJ 3225 Help with Intervals --线段树区间操作
- poj 3225 线段树区间更新,区间询问 Help with Intervals
- poj 3225 Help with Intervals(线段树+区间的交集,差集,补集,并集)好难的题目,一天了,真是纠结
- POJ 3225 Help with Intervals【线段树 区间更新 异或运算】
- POJ 3225 Help with Intervals 线段树 成段更新
- POJ 3225 Help with Intervals(线段树)
- POJ 3225 - Help with Intervals
- POJ 3225 Help with Intervals(线段树)
- 【POJ】3225 Help with Intervals
- POJ 3225——Help with Intervals(线段树,成段替换+区间异或+hash)
- POJ 3225 (线段树 区间更新) Help with Intervals
- POJ 3225 Help with Intervals
- POJ 3225 Help with Intervals 线段树 成段更新
- POJ 3225 - Help with Intervals(线段树)
- POJ 3225 Help with Intervals 【线段树】
- POJ 3225 Help with Intervals
- POJ 3225 Help with Intervals 线段树
- POJ 3225 Help with Intervals (线段树 成段更新, 懒惰标记*2)
- POJ 3225 Help with Intervals(线段树)