POJ 3225 Help with Intervals --线段树区间操作
题意:给你一些区间操作,让你输出最后得出的区间。
解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题。
线段树维护两个值: cov 和 rev ,一个是覆盖标记,0表示此区间被0覆盖,1表示被1覆盖,-1表示未被覆盖, rev为反转标记,rev = 1表示反转,0表示不翻转
所以集合操作可以化为如下区间操作:
U l r: 把区间[l,r]覆盖成1
I l r: 把[0,l)(r,MAX]覆盖成0
D l r: 把区间[l,r]覆盖成0
C l r: 把[0,l)(r,MAX]覆盖成0 , 且[l,r]区间0/1互换
S l r: [l,r]区间0/1互换
重点在于pushdown函数以及边界处理。
代码:
#include <iostream>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define N (65536*2) struct Tree
{
int cov,rev; //cov -1 rev 0
}tree[*N]; struct ANS
{
char L,R;
int A,B;
}ans[N+];
int cnt; void build(int l,int r,int rt)
{
tree[rt].cov = ;
tree[rt].rev = ;
if(l == r) return;
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
} void pushdown(int l,int r,int rt)
{
if(tree[rt].cov != -)
{
tree[*rt].cov = tree[*rt+].cov = tree[rt].cov;
tree[*rt].rev = tree[*rt+].rev = ;
tree[rt].cov = -;
}
if(tree[rt].rev)
{
if(tree[*rt].cov != -)
tree[*rt].cov ^= ;
else
tree[*rt].rev ^= ; if(tree[*rt+].cov != -)
tree[*rt+].cov ^= ;
else
tree[*rt+].rev ^= ;
tree[rt].rev = ;
}
} void update(int l,int r,int aa,int bb,int op,int rt)
{
if(aa > bb || aa < ) return; //必须要加,否则会RE
if(aa <= l && bb >= r)
{
if(op != ) //cover to 0/1
{
tree[rt].cov = op;
tree[rt].rev = ;
}
else //op == 2 reverse
{
if(tree[rt].cov != -)
tree[rt].cov ^= ;
else
tree[rt].rev ^= ;
}
return;
}
pushdown(l,r,rt);
int mid = (l+r)/;
if(aa <= mid)
update(l,mid,aa,bb,op,*rt);
if(bb > mid)
update(mid+,r,aa,bb,op,*rt+);
} void query(int l,int r,int rt)
{
if(tree[rt].cov == )
{
ans[cnt].L = (l%==)?'(':'[';
ans[cnt].A = l/;
ans[cnt].R = (r%==)?')':']';
ans[cnt].B = (r+)/;
cnt++;
}
else if(tree[rt].cov == ) return;
else
{
pushdown(l,r,rt);
int mid = (l+r)/;
query(l,mid,*rt);
query(mid+,r,*rt+);
}
} void print()
{
char nowl,nowr;
int nowA,nowB;
if(cnt == )
puts("empty set");
else
{
nowl = ans[].L;
nowr = ans[].R;
nowA = ans[].A;
nowB = ans[].B;
for(int i=;i<cnt;i++)
{
if(ans[i].A == nowB && (nowr == ']' || ans[i].L == '['))
{
nowB = ans[i].B;
nowr = ans[i].R;
}
else
{
printf("%c%d,%d%c ",nowl,nowA,nowB,nowr);
nowl = ans[i].L;
nowr = ans[i].R;
nowA = ans[i].A;
nowB = ans[i].B;
}
}
printf("%c%d,%d%c\n",nowl,nowA,nowB,nowr);
}
} int main()
{
int a,b;
char L,R,op;
int n = *;
build(,n,);
while(scanf("%c %c%d,%d%c\n",&op,&L,&a,&b,&R)!=EOF) // '\n' 务必要加
{
a = *a; if(L == '(') a++;
b = *b; if(R == ')') b--;
if(a > b || a < ) continue;
if(op == 'U') //并集
update(,n,a,b,,);
else if(op == 'I')
{
update(,n,,a-,,);
update(,n,b+,n,,);
}
else if(op == 'D')
update(,n,a,b,,);
else if(op == 'C')
{
update(,n,,a-,,);
update(,n,b+,n,,);
update(,n,a,b,,);
}
else
update(,n,a,b,,);
}
cnt = ;
query(,n,);
print();
return ;
}
参考文章: http://my.oschina.net/llmm/blog/124256
POJ 3225 Help with Intervals --线段树区间操作的更多相关文章
- poj 3225 Help with Intervals(线段树,区间更新)
Help with Intervals Time Limit: 6000MS Memory Limit: 131072K Total Submissions: 12474 Accepted: ...
- (中等) POJ 3225 Help with Intervals , 线段树+集合。
Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While ...
- POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)
POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...
- POJ 2528 Mayor's posters (线段树区间更新+离散化)
题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...
- POJ 2528 ——Mayor's posters(线段树+区间操作)
Time limit 1000 ms Memory limit 65536 kB Description The citizens of Bytetown, AB, could not stand t ...
- Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...
- 线段树(区间操作) POJ 3325 Help with Intervals
题目传送门 题意:四种集合的操作,对应区间的01,问最后存在集合存在的区间. 分析:U T [l, r]填充1; I T [0, l), (r, N]填充0; D T [l, r]填充0; C T[0 ...
- poj 2528 Mayor's posters 线段树区间更新
Mayor's posters Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Descript ...
- hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】
Tunnel Warfare Time Limit: 4000/2000 MS ...
随机推荐
- quartz使用(一)
在项目中经常会碰到定时任务,quartz是一款非常优秀的开源框架, 提供了定时任务的支持,还支持任务的持久化,并且提供了对数据库的支持.下面首先对quartz做一个简单介绍,并附上一个小例子. 1.下 ...
- java微信开发
所谓的微信开发就是在微信开发模式之下,对微信进行公众号和企业号的扩展开发. 如果要让你的微信公众号有更多的功能,比如菜单支持,自动的信息服务,查询,消息推送等,就必须开启微信的开发模式.进入微 ...
- SharePoint 2013 列表多表联合查询
在SharePoint的企业应用中,遇到复杂的逻辑的时候,我们会需要多表查询:SharePoint和Sql数据表一样,也支持多表联合查询,但是不像Sql语句那样简单,需要使用SPQuery的Joins ...
- SparseArray<E>详解
SparseArray<E> 是官方推荐的用来替代 HashMap<Integer, E> 的一个工具类,相比来说有着更好的性能(其核心是折半查找函数(binarySearch ...
- Python基础(4)--字符串
所有标准的序列操作对字符串都适用,但字符串是不可变的 本文地址:http://www.cnblogs.com/archimedes/p/python-string.html,转载请注明源地址. 字符串 ...
- iOS 学习 - 5.UILabel设置行距
NSMutableAttributedString *arrString =[[NSMutableAttributedString alloc]initWithString:@"asdass ...
- iOS 开发技巧-制作环形进度条
有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现. 先看一下这篇博客,博客地址:ht ...
- iOS实现三屏复用循环广告[从服务器请求的广告]
循环广告我们在开发中已经是熟得不能再熟了,今天整理这篇scrollview三屏复用广告 原理使用scrollview里的三个imageview分别去加载不同的图片,用少量的资源来显示大量或不确定的广告 ...
- XCode的代码块备份
以上三个的注释可以从下面的代码依据个数拷贝和删除: /** * <#comment#> * * @param <#one#> * * @param <#two#> ...
- Android Studio 有用的插件
从Eclipse切换到Android Studio 有一段时间了,发现as同,github,已经很多插件的集合有强大的合成效应. 安装插件请参考:http://blog.csdn.net/hyr839 ...