poj 3225 间隙(横截面和填充操作)

简介:

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;
}


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






本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4870050.html,如需转载请自行联系原作者


相关文章
|
4天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1106 0
|
3天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
532 10
|
13天前
|
人工智能 运维 安全
|
12天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。
|
4天前
|
弹性计算 Kubernetes jenkins
如何在 ECS/EKS 集群中有效使用 Jenkins
本文探讨了如何将 Jenkins 与 AWS ECS 和 EKS 集群集成,以构建高效、灵活且具备自动扩缩容能力的 CI/CD 流水线,提升软件交付效率并优化资源成本。
301 0
|
11天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
12天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
807 23
|
4天前
|
缓存 供应链 监控
VVIC seller_search 排行榜搜索接口深度分析及 Python 实现
VVIC搜款网seller_search接口提供服装批发市场的商品及商家排行榜数据,涵盖热销榜、销量排名、类目趋势等,支持多维度筛选与数据分析,助力选品决策、竞品分析与市场预测,为服装供应链提供有力数据支撑。
|
4天前
|
缓存 监控 API
Amazon item_review 商品评论接口深度分析及 Python 实现
亚马逊商品评论接口(item_review)可获取用户评分、评论内容及时间等数据,支持多维度筛选与分页调用,结合Python实现情感分析、关键词提取与可视化,助力竞品分析、产品优化与市场决策。

热门文章

最新文章