POJ 3225 Help with Intervals(线段树)
这题纠结了两天,开始一点思路没有,后来看到有大牛把这题的做法称作区间树,并说明了区间树与线段树的区别(区间树是区间内被染色的区间标记为1,未被染色的区间标记为0)。我觉得这就是线段树的一类操作,没有必要分出去吧。。。
思路:区间更新,首先想到的应该是Lazy思想;这题分五种情况:
Command | Semantics |
---|---|
U T
|
S ← S ∪ T |
I T
|
S ← S ∩ T |
D T
|
S ← S − T |
C T
|
S ← T − S |
S T
|
S ← S ⊕ T |
U:直接将T对应的区间覆盖为1;
I:将T的补区间(比如T[l, r], 补区间就是[0, l-1], [r+1, N])清零即可;
D:直接将T区间清零;
C:先将T的补区间清零,再对T区间取反;
S:直接对T区间取反;
(把这几个操作在纸上写写,马上就明白了。)
然后就是剩下的线段树的区间更新、区间上传、区间下分了。
Code:
#include <iostream>#include <cstdio>#include <cstring>#define L(t) t << 1#define R(t) t << 1 | 1using namespace std; const int N = 65540*2; class node{public:int l, r;int cov;int change; //表示该区间是否需要被改变;void changeEdit(){ //按change进行操作if(change) change = 0; //如果需要改变,当前区间标为不需要else if(cov != -1) cov ^= 1; //如果当前段非单色, 对他进行^改变else change = 1; }}node[N*4]; int flag[N]; // 下分void PushDown(int t){if(node[t].cov != -1){ node[L(t)].cov = node[R(t)].cov = node[t].cov; node[L(t)].change = node[R(t)].change = node[t].change; }if(node[t].change){ node[L(t)].changeEdit(); node[R(t)].changeEdit(); node[t].change = 0; }}//上传void PushUp(int t){if(node[L(t)].cov == node[R(t)].cov){ node[t].cov = node[L(t)].cov; } else { node[t].cov = -1; }} void creat(int t, int l, int r){ node[t].l = l; node[t].r = r; node[t].cov = 0; node[t].change = 0; if(l == r) return ; int mid = (l + r) >> 1; creat(L(t), l, mid); creat(R(t), mid+1, r);} void updata(int t, int l, int r, int v){if(node[t].l > l || node[t].r < r) return ; if(node[t].l >= l && node[t].r <= r){//printf("%d %d %d\n", l, r, v); node[t].cov = v; node[t].change = 0;return ; } PushDown(t);int mid = (node[t].l + node[t].r) >> 1; if(l > mid) updata(R(t), l, r, v);else if(r <= mid) updata(L(t), l, r, v);else{ updata(L(t), l, mid, v); updata(R(t), mid+1, r, v); } PushUp(t);} void XOR(int t, int l, int r){if(node[t].l > l || node[t].r < r) return ; if(node[t].l == l && node[t].r == r){//printf("%d %d %d\n", l, r, node[t].cov);if(node[t].cov != -1) node[t].cov ^= 1;else node[t].change ^= 1;return ; } PushDown(t);int mid = (node[t].l + node[t].r) >> 1; if(l > mid) XOR(R(t), l, r);else if(r <= mid) XOR(L(t), l, r);else{ XOR(L(t), l, mid); XOR(R(t), mid + 1, r); } PushUp(t);} void query(int t){if(node[t].l == node[t].r){ flag[node[t].l] = node[t].cov;return ; } PushDown(t); query(L(t)); query(R(t));} int main(){//freopen("data.in", "r", stdin); int l, r, i;char s, p, q; creat(1, 0, N); while(~scanf("%c %c%d,%d%c\n", &s, &p, &l, &r, &q)){ l *= 2; r *= 2;if(p == '(') l++;if(q == ')') r--; if(s == 'U'){ updata(1, l, r, 1); } else if(s == 'I'){if(l > 0) updata(1, 0, l - 1, 0);if(r < N) updata(1, r + 1, N, 0); } else if(s == 'D'){ updata(1, l, r, 0); } else if(s == 'C'){if(l > 0) updata(1, 0, l - 1, 0);if(r < N) updata(1, r + 1, N, 0); XOR(1, l, r); } else{ XOR(1, l, r); } } query(1);int begin, end, tmp = 1;for(i = 0; i <= N; i++){while(i <= N && !flag[i]) i++; begin = i;if(i > N) break; while(i <= N && flag[i]) i++; end = i - 1; tmp = 0; if(begin&1){ printf("(%d,", begin/2); } else{ printf("[%d,", begin/2); } if(end&1){ printf("%d) ", (end+1)/2); }else{ printf("%d] ", end/2); } }if(tmp) printf("empty set"); putchar('\n');return 0;}
POJ 3225 Help with Intervals(线段树)相关推荐
- POJ 1177 Picture [离散化+扫描线+线段树]
http://poj.org/problem?id=1177 给若干矩形,求被覆盖的区域的周长. 将 y 坐标离散化后,按 x 坐标进行扫描.用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 ...
- POJ 3264 Balanced Lineup【线段树区间查询求最大值和最小值】
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 53703 Accepted: 25237 ...
- poj 2777 AND hdu 5316 线段树
区间染色问题,用线段树可以解决.颜色总类不多,故考虑用二进制数的每一位表示一种颜色,然后父节点的颜色就是孩子节点颜色"或"起来,加上lazy标记,轻松AC. poj 2777: 1 ...
- POJ 2777 Count Color (线段树区间修改 + 状态压缩)
题目链接:POJ 2777 Count Color [题目大意] 给你 n 块板子, 编号1--n , 板子的颜色最多30种, 初始时 板子的颜色都是 1: 有两种操作 1 .把给定区间的板子染成一 ...
- POJ——3624 Balanced Lineup(线段树入门——区间最值问题)
原题链接:http://poj.org/problem?id=3264 每天挤奶时,农夫John的N头奶牛(1≤N≤50,000头)总是按照相同的顺序排列.一天,农夫约翰决定和几头牛组织一场极限飞盘游 ...
- poj 2985(并查集+线段树求K大数)
解题思路:这道题并查集很容易,合并时找到父节点就直接加上去就ok了.关键是如何求K大数,我一直在想用线段树怎么写,一开始想如果直接记录数的大小那肯定是没戏了,借鉴了一下别人的思路:区间[a,b]记录的 ...
- poj 2528 Mayor's posters (线段树+离散化)
/*离散化+线段树由于 数据的输入最大是 10000000 ,直接用开数组肯点会超,所以要将起离散话,首先 ,我们存储输入的边,将其离散化,后面的就和一般的线段树一样可. */#include< ...
- Poj 3246 Balanced Lineup(线段树基础)
依旧是线段树基础题 询问区间的最大值和最小值之差,只有询问,没有插入删除.继续理解基础线段树 #include <iostream> #include <algorithm> ...
- POJ 3264 Balanced Lineup 【线段树】
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 50004 Accepted: 23434 Cas ...
最新文章
- python3菜鸟教程中文-Python3 字符串
- Winform中实现中文验证码(附代码下载)
- Maven软件的下载安装
- UNIX网络编程——解决TCP网络传输“粘包”问题
- Spring MVC:MySQL和Hibernate的安全性
- MyEclipse 皮肤、主题、背景色
- python输出引号内的变量值_引号中的Python变量值
- 按键精灵手机版去除广告XPosed模块插件
- 根据 List 元素中的某个字段大小排序
- 英特尔第十代处理器为什么不支持win7_为什么i7处理器不支持win7系统,背后的真实原因?...
- QComboBox下拉框给选项增加删除按钮
- 计算机组成原理中英文名词对照_持续更新
- 吴恩达深度学习笔记(五)
- (2/2) sharex录制屏幕没有声音,升级高版本的 sharex
- Wangle源码分析:Service
- 分享如何恢复回收站删除文件的办法
- 前端请求接口报405错误
- 不容错过的Java高级面试题
- 下载RoboWare Studio官网登录不上去
- 小学计算机课认识键盘,教学设计:《认识键盘》
热门文章
- jenkins如何实现重新发布历史构建记录里的版本
- angularjs 日期倒计时效果
- 数据结构 排序(希尔排序)
- linux :故障提示:Error:No suitable device found: no device found for connection System eth0
- Power BI for Office 365(七) Power BI站点
- jquery 鼠标经过显示 信息小卡片
- 富有客户端技术之——jQuery EasyUI
- 申请加入 “WebGIS” 团队
- QWidget子窗口中setStyleSheet无效,解决方法
- Ubuntu 14.04更新为国内阿里源解决apt-get install无法执行的问题