http://poj.org/problem?id=3225

一道题又做了一天。

。这道题对我来说起初有N多难点。

1:区间的开闭怎样解决。

2:如何把区间的交并补、对称差转化为对线段树的操作。

后来与实验室的同学讨论了后攻克了前面两个问题。

对于区间的开闭,能够将区间放大一倍,偶数点表示端点。奇数点表示区间内线段,前开的话左端点加1,右开的话右端点减1。比如[1,3]能够表示成[2,6],(1,3)表示成(3,5)。



对于区间的交并补问题,能够转化为区间覆盖问题。若T区间为[a,b]。

U T:[a,b]覆盖为1.

I T:[0,a-1] [b+1,maxn] 覆盖为0

D T:[a,b]覆盖为0

C T:[0,a-1] [b+1,maxn] 覆盖为0,[a,b]取反

S T:[a,b]取反



然后处理区间的覆盖和异或操作。

起初对异或操作没想到lazy,考虑到异或的性质。两次异或相当于没变。所以节点附加两个信息:col,rev。

col表示覆盖信息,col=0说明全被覆盖为0。col=1说明全被覆盖为1,col=-1说明没有全被覆盖。

rev表示异或信息,rev=1说明区间总体异或,rev=0说明不用异或。

可见仅仅有当col=-1时rev才实用。更新时。若是区间覆盖,对应区间覆盖后抹去异或操作。若是异或操作,推断区间是否全然覆盖。若是直接异或,否则rev进行异或。push_down的时候,若区间全然覆盖,将覆盖信息推送下去并将左右儿子的异或操作抹去,若区间没有全然覆盖,必然有异或操作,将左右儿子能够异或的异或掉,不能异或的将其rev异或。

#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
//#define LL long long
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 131072; struct node
{
int l,r;
int col;
int rev;
}tree[maxn*4]; char s1[10],s2[10];
int a[maxn+10]; void build(int v, int l, int r)
{
tree[v].l = l;
tree[v].r = r;
tree[v].col = 0;
tree[v].rev = 0;
if(l == r)
return;
int mid = (l+r)>>1;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
} void push_down(int v)
{
if(tree[v].l == tree[v].r)
return;
if(tree[v].col != -1) //区间被全然覆盖
{
tree[v*2].col = tree[v*2+1].col = tree[v].col; //向下推送。并把自己的col置为-1
tree[v].col = -1;
tree[v].rev = 0;
tree[v*2].rev = tree[v*2+1].rev = 0; //儿子节点也被全然覆盖,因此抹去异或操作
}
if(tree[v].rev) //区间没被全然覆盖且须要异或
{
if(tree[v*2].col != -1) //儿子节点被全然覆盖,直接异或
tree[v*2].col ^= 1;
else tree[v*2].rev ^= 1;//否则rev进行异或。 if(tree[v*2+1].col != -1)
tree[v*2+1].col ^= 1;
else tree[v*2+1].rev ^= 1;
tree[v].rev = 0;
}
} void update(int v, int l, int r, int col)
{
if(l > r) //l > r的区间忽略不计
return;
if(tree[v].l == l && tree[v].r == r)
{
if(col == 0 || col == 1)
{
tree[v].col = col;
tree[v].rev = 0;
}
else
{
if(tree[v].col != -1)
tree[v].col ^= 1;
else
tree[v].rev ^= 1;
}
return;
}
push_down(v);
int mid = (tree[v].l + tree[v].r) >> 1;
if(r <= mid)
update(v*2,l,r,col);
else if(l > mid)
update(v*2+1,l,r,col);
else
{
update(v*2,l,mid,col);
update(v*2+1,mid+1,r,col);
}
} void query(int v)
{
if(tree[v].col == 1)
{
for(int i = tree[v].l; i <= tree[v].r; i++)
a[i] = tree[v].col;
return;
}
if(tree[v].col == 0)
return;
if(tree[v].l == tree[v].r)
return;
push_down(v);
query(v*2);
query(v*2+1);
} int main()
{
build(1,0,maxn);
int l,r,len;
memset(a,0,sizeof(a));
while(~scanf("%s %s",s1,s2))
{
l = 0;
r = 0;
len = strlen(s2);
int i;
for(i = 1; s2[i] >= '0' && s2[i] <= '9'; i++)
l = l*10 + s2[i]-'0';
i++;
for(; s2[i] >= '0' && s2[i] <= '9'; i++)
r = r*10 + s2[i]-'0'; if(s2[0] == '[')
l = l*2;
else l = l*2+1;
if(s2[len-1] == ']')
r = r*2;
else r = r*2-1; if(s1[0] == 'U')
{
update(1,l,r,1);
}
else if(s1[0] == 'I')
{
update(1,0,l-1,0);
update(1,r+1,maxn,0);
}
else if(s1[0] == 'D')
{
update(1,l,r,0);
}
else if(s1[0] == 'C')
{
update(1,0,l-1,0);
update(1,r+1,maxn,0);
update(1,l,r,2); //取反
}
else
{
update(1,l,r,2);//取反
}
} query(1);
int flag = 0; for(int i = 0; i < maxn; i++)
{
if(a[i] == 1 && (i == 0 || a[i-1] == 0)) l = i;
if(a[i] == 1 && (i == maxn-1 || a[i+1] == 0))
{
if(flag == 0) flag = 1;
else printf(" ");
if(l%2)
printf("(");
else printf("[");
printf("%d,",l/2);
printf("%d",(i+1)/2);
if(i%2)
printf(")");
else printf("]");
}
}
if(flag == 0)
printf("empty set\n");
else printf("\n");
return 0;
}

做了hdu 3379,又尝试了一种写法,就是将上面的col和rev合并起来,由于它们是相互排斥的,一个节点仅仅会有一个信息。

所以仅仅用col表示。col为2时表示取反。为-1表示不操作。若開始是-1,当两次取反后又变回-1。

#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
//#define LL long long
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 131072; struct node
{
int l,r;
int col;
}tree[maxn*4]; char s1[10],s2[10];
int a[maxn+10]; void build(int v, int l, int r)
{
tree[v].l = l;
tree[v].r = r;
tree[v].col = 0;
if(l == r)
return;
int mid = (l+r)>>1;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
} void push_down(int v)
{
if(tree[v].col == -1 || tree[v].l == tree[v].r)
return;
if(tree[v].col == 0 || tree[v].col == 1)
{
tree[v*2].col = tree[v*2+1].col = tree[v].col;
}
else
{
if(tree[v*2].col == 0 || tree[v*2].col == 1)
tree[v*2].col ^= 1;
else
tree[v*2].col = 1-tree[v*2].col; if(tree[v*2+1].col == 0 || tree[v*2+1].col == 1)
tree[v*2+1].col ^= 1;
else tree[v*2+1].col = 1-tree[v*2+1].col;
}
tree[v].col = -1;
return;
} void update(int v, int l, int r, int col)
{
if(l > r)
return;
if(tree[v].l == l && tree[v].r == r)
{
if(col == 0 || col == 1)
{
tree[v].col = col;
}
else
{
if(tree[v].col == 0 || tree[v].col == 1)
tree[v].col ^= 1;
else tree[v].col = 1-tree[v].col;
}
return;
}
push_down(v); int mid = (tree[v].l + tree[v].r) >> 1;
if(r <= mid)
update(v*2,l,r,col);
else if(l > mid)
update(v*2+1,l,r,col);
else
{
update(v*2,l,mid,col);
update(v*2+1,mid+1,r,col);
}
} void query(int v)
{
if(tree[v].col == 1)
{
for(int i = tree[v].l; i <= tree[v].r; i++)
a[i] = tree[v].col;
return;
}
if(tree[v].col == 0)
return;
if(tree[v].l == tree[v].r)
return;
push_down(v);
query(v*2);
query(v*2+1);
} int main()
{
build(1,0,maxn);
int l,r,len;
memset(a,0,sizeof(a));
while(~scanf("%s %s",s1,s2))
{
l = 0;
r = 0;
len = strlen(s2);
int i;
for(i = 1; s2[i] >= '0' && s2[i] <= '9'; i++)
l = l*10 + s2[i]-'0';
i++;
for(; s2[i] >= '0' && s2[i] <= '9'; i++)
r = r*10 + s2[i]-'0'; if(s2[0] == '[')
l = l*2;
else l = l*2+1;
if(s2[len-1] == ']')
r = r*2;
else r = r*2-1; if(s1[0] == 'U')
{
update(1,l,r,1);
}
else if(s1[0] == 'I')
{
update(1,0,l-1,0);
update(1,r+1,maxn,0);
}
else if(s1[0] == 'D')
{
update(1,l,r,0);
}
else if(s1[0] == 'C')
{
update(1,0,l-1,0);
update(1,r+1,maxn,0);
update(1,l,r,2); //取反
}
else
{
update(1,l,r,2);//取反
}
} query(1);
int flag = 0; for(int i = 0; i < maxn; i++)
{
if(a[i] == 1 && (i == 0 || a[i-1] == 0)) l = i;
if(a[i] == 1 && (i == maxn-1 || a[i+1] == 0))
{
if(flag == 0) flag = 1;
else printf(" ");
if(l%2)
printf("(");
else printf("[");
printf("%d,",l/2);
printf("%d",(i+1)/2);
if(i%2)
printf(")");
else printf("]");
}
}
if(flag == 0)
printf("empty set\n");
else printf("\n");
return 0;
}

版权声明:本文博主原创文章。博客,未经同意不得转载。

poj 3225 间隙(横截面和填充操作)的更多相关文章

  1. ●线段树的三个题(poj 3225,hdu 1542,hdu 1828)

    ●poj 3225 Help with Intervals(线段树区间问题) ○赘述题目 给出以下集合操作: 然后有初始的一个空集S,和以下题目给出的操作指令,并输入指令: 要求进行指令操作后,按格式 ...

  2. POJ 3225 Help with Intervals(线段树)

    POJ 3225 Help with Intervals 题目链接 集合数字有的为1,没有为0,那么几种操作相应就是置为0或置为1或者翻转,这个随便推推就能够了,然后开闭区间的处理方式就是把区间扩大成 ...

  3. poj 3225 【线段树】

    poj 3225 这题是用线段树解决区间问题,看了两天多,算是理解一点了. Description LogLoader, Inc. is a company specialized in provid ...

  4. POJ 3225 Help with Intervals --线段树区间操作

    题意:给你一些区间操作,让你输出最后得出的区间. 解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题. 线段树维护两个值: cov ...

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

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

  6. poj - 3225 Roadblocks(次短路)

    http://poj.org/problem?id=3255 bessie 有时会去拜访她的朋友,但是她不想走最快回家的那条路,而是想走一条比最短的路长的次短路. 城镇由R条双向路组成,有N个路口.标 ...

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

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

  8. POJ 3225.Help with Intervals-线段树(成段替换、区间异或、简单hash)

    POJ3225.Help with Intervals 这个题就是对区间的各种操作,感觉这道题写的一点意思都没有,写到后面都不想写了,而且更神奇的是,自己的编译器连结果都输不出来,但是交上就过了,也是 ...

  9. poj 3225 线段树+位运算

    略复杂的一道题,首先要处理开闭区间问题,扩大两倍即可,注意输入最后要\n,初始化不能随便memset 采用线段树,对线段区间进行0,1标记表示该区间是否包含在s内U T S ← S ∪ T 即将[l, ...

随机推荐

  1. MFC模态对话框的消息循环

    MFC模态对话框的消息循环 单线程程序, 当主窗口响应函数中弹出模态对话框时,为什么主窗口响应函数可能照常工作? 当弹出模态对话框时,线程的消息循环无法返回,父窗口的事件本应没人处理,应该处于卡死状态 ...

  2. Invalid character constant

    Invalid character constant 无效的字符常数 可能是双引号写成了单引号了.

  3. NYOJ 12 喷水装置(二)

    pid=12">喷水装置(二) 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描写叙述 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n( ...

  4. Codeforces 164 E Compatible Numbers

    主题链接~~> 做题情绪:好题,做拉的比赛的时候想了非常久,想到枚举变幻某一位的 0 为 1 .可是每一个数都这样枚举岂不超时的节奏,当时没想到事实上从大到小枚举一次就 ok 了. 解题思路: ...

  5. HTML5: Screen Orientation API

    媒体的询问取决于智能手机和平板布局调整的方向一致网站.但有时候你被锁定在一个希腊网站特定方向.横向或纵向.此时,是本机格式可以指定保健应用. APP只显示在一个预设格式-独立于实际设备方向.通过使用H ...

  6. linux yum命令

    1 安装yum install 全部安装yum install package1 安装指定的安装包package1yum groupinsall group1 安装程序组group1 2 更新和升级y ...

  7. [POJ 3735] Training little cats (结构矩阵、矩阵高速功率)

    Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9613   Accepted: 2 ...

  8. JSTL自定义标签库 (二)

    要定义自己的标签,首先写个java类,extends TagSupport  或者 implements Tag ,然后在类体里实现自己想要的方法,或者覆盖父类的方法. 我定义的MyTag代码如下: ...

  9. GString及IntelliJIdea中调试Groovy的操作步骤

    今天是学习Groovy的第一天,首先我觉得学习任何一种语言都要先弄清楚这种语言的特性,因为只有了解了特性之后学习才能达到好的效果,那么groovy的特点是什么的.我觉得groovy是一种动态语言,动态 ...

  10. Unity3D发布WebPlayer时Failed to download data file解决方案

    今天发布WebPlayer时, 发现直接打开html是可以正常运行的, 但是通过iis访问的话就会报错: Failed to download data file. 一开始以为是防火墙, 后来发现不是 ...