题意:给你一些区间操作,让你输出最后得出的区间。

解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以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 --线段树区间操作的更多相关文章

  1. poj 3225 Help with Intervals(线段树,区间更新)

    Help with Intervals Time Limit: 6000MS   Memory Limit: 131072K Total Submissions: 12474   Accepted:  ...

  2. (中等) POJ 3225 Help with Intervals , 线段树+集合。

    Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While ...

  3. POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)

    POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...

  4. POJ 2528 Mayor's posters (线段树区间更新+离散化)

    题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...

  5. POJ 2528 ——Mayor's posters(线段树+区间操作)

    Time limit 1000 ms Memory limit 65536 kB Description The citizens of Bytetown, AB, could not stand t ...

  6. Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...

  7. 线段树(区间操作) 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 ...

  8. poj 2528 Mayor's posters 线段树区间更新

    Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Descript ...

  9. hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】

    Tunnel Warfare                                                             Time Limit: 4000/2000 MS ...

随机推荐

  1. quartz使用(一)

    在项目中经常会碰到定时任务,quartz是一款非常优秀的开源框架, 提供了定时任务的支持,还支持任务的持久化,并且提供了对数据库的支持.下面首先对quartz做一个简单介绍,并附上一个小例子. 1.下 ...

  2. java微信开发

    所谓的微信开发就是在微信开发模式之下,对微信进行公众号和企业号的扩展开发.     如果要让你的微信公众号有更多的功能,比如菜单支持,自动的信息服务,查询,消息推送等,就必须开启微信的开发模式.进入微 ...

  3. SharePoint 2013 列表多表联合查询

    在SharePoint的企业应用中,遇到复杂的逻辑的时候,我们会需要多表查询:SharePoint和Sql数据表一样,也支持多表联合查询,但是不像Sql语句那样简单,需要使用SPQuery的Joins ...

  4. SparseArray<E>详解

    SparseArray<E> 是官方推荐的用来替代 HashMap<Integer, E> 的一个工具类,相比来说有着更好的性能(其核心是折半查找函数(binarySearch ...

  5. Python基础(4)--字符串

    所有标准的序列操作对字符串都适用,但字符串是不可变的 本文地址:http://www.cnblogs.com/archimedes/p/python-string.html,转载请注明源地址. 字符串 ...

  6. iOS 学习 - 5.UILabel设置行距

    NSMutableAttributedString *arrString =[[NSMutableAttributedString alloc]initWithString:@"asdass ...

  7. iOS 开发技巧-制作环形进度条

    有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现. 先看一下这篇博客,博客地址:ht ...

  8. iOS实现三屏复用循环广告[从服务器请求的广告]

    循环广告我们在开发中已经是熟得不能再熟了,今天整理这篇scrollview三屏复用广告 原理使用scrollview里的三个imageview分别去加载不同的图片,用少量的资源来显示大量或不确定的广告 ...

  9. XCode的代码块备份

    以上三个的注释可以从下面的代码依据个数拷贝和删除: /** * <#comment#> * * @param <#one#> * * @param <#two#> ...

  10. Android Studio 有用的插件

    从Eclipse切换到Android Studio 有一段时间了,发现as同,github,已经很多插件的集合有强大的合成效应. 安装插件请参考:http://blog.csdn.net/hyr839 ...