【线段树】bzoj3995 [SDOI2015]道路修建

本文详细介绍了一种特殊的线段树实现方式,每个节点维护五个特定状态,用于解决区间更新和查询问题。通过递归构建和更新树结构,并提供查询功能,适用于处理复杂的区间操作。

线段树每个结点维护5个域:

整个区间的MST。

将两个左端点连通,两个右端点不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块。

将两个右端点连通,两个左端点不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块。

两个左端点不连通,两个右端点也不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块。(就是上面一条线,下面一条线)

两个左端点不连通,两个右端点也不连通,整个区间内选择2*(r-l+1)-3条边的最小生成森林,有3个连通块。

合并时讨论5*5*2(两条夹缝里的横边是否都选择)种情况。

/*每个结点维护5个域:左右完全连通,左连通右不连通,右连通左不连通,左右都不连通2,左右都不连通3*/
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 60001
#define INF 1000000000
int n,m,heng[2][N],zong[N];
struct Node
{
	int z1y1,z1y0,z0y1,z0y02,z0y03;
	void reset(){z1y1=z1y0=z0y1=z0y02=z0y03=INF;}
}T[N<<2];
inline void pushup(Node &rt,const Node &ls,const Node &rs,const int &r1,const int &l1,const int &l2)
{
	rt.reset();
	
	int MIN=min(heng[0][r1],heng[1][r1]),SUM=heng[0][r1]+heng[1][r1];
	
	/*z1y1+z1y1*/rt.z1y1=ls.z1y1+rs.z1y1+MIN;
	if(l2>1)/*z1y1+z1y0*/rt.z1y0=ls.z1y1+rs.z1y0+MIN;
	if(l2>1)/*z1y1+z0y1*/rt.z1y1=min(rt.z1y1,ls.z1y1+rs.z0y1+SUM);
	/*z1y1+z0y02*/rt.z1y1=min(rt.z1y1,ls.z1y1+rs.z0y02+SUM);
				  rt.z1y0=min(rt.z1y0,ls.z1y1+rs.z0y02+MIN);
	if(l2>1)/*z1y1+z0y03*/rt.z1y0=min(rt.z1y0,ls.z1y1+rs.z0y03+SUM);
	
	if(l1>1)/*z1y0+z1y1*/rt.z1y1=min(rt.z1y1,ls.z1y0+rs.z1y1+SUM);
	if(l1>1&&l2>1)/*z1y0+z1y0*/rt.z1y0=min(rt.z1y0,ls.z1y0+rs.z1y0+SUM);
	/*z1y0+z0y1不合法*/
	if(l1>1)/*z1y0+z0y02*/rt.z1y0=min(rt.z1y0,ls.z1y0+rs.z0y02+SUM);
	/*z1y0+z0y03不合法*/
	
	if(l1>1)/*z0y1+z1y1*/rt.z0y1=ls.z0y1+rs.z1y1+MIN;
	if(l1>1&&l2>1)/*z0y1+z1y0*/rt.z0y03=ls.z0y1+rs.z1y0+MIN;
	if(l1>1&&l2>1)/*z0y1+z0y1*/rt.z0y1=min(rt.z0y1,ls.z0y1+rs.z0y1+SUM);
	if(l1>1)/*z0y1+z0y02*/rt.z0y1=min(rt.z0y1,ls.z0y1+rs.z0y02+SUM),
				  		  rt.z0y03=min(rt.z0y03,ls.z0y1+rs.z0y02+MIN);
	if(l1>1&&l2>1)/*z0y1+z0y03*/rt.z0y03=min(rt.z0y03,ls.z0y1+rs.z0y03+SUM);
	
	/*z0y02+z1y1*/rt.z1y1=min(rt.z1y1,ls.z0y02+rs.z1y1+SUM);
				  rt.z0y1=min(rt.z0y1,ls.z0y02+rs.z1y1+MIN);
	if(l2>1)/*z0y02+z1y0*/rt.z1y0=min(rt.z1y0,ls.z0y02+rs.z1y0+SUM),
						  rt.z0y03=min(rt.z0y03,ls.z0y02+rs.z1y0+MIN);
	if(l2>1)/*z0y02+z0y1*/rt.z0y1=min(rt.z0y1,ls.z0y02+rs.z0y1+SUM);
	/*z0y02+z0y02*/rt.z0y02=ls.z0y02+rs.z0y02+SUM;
				   rt.z0y03=min(rt.z0y03,ls.z0y02+rs.z0y02+MIN);
	if(l2>1)/*z0y02+z0y03*/rt.z0y03=min(rt.z0y03,ls.z0y02+rs.z0y03+SUM);
	
	if(l1>1)/*z0y03+z1y1*/rt.z0y1=min(rt.z0y1,ls.z0y03+rs.z1y1+SUM);
	if(l1>1&&l2>1)/*z0y03+z1y0*/rt.z0y03=min(rt.z0y03,ls.z0y03+rs.z1y0+SUM);
	/*z0y03+z0y1不合法*/
	if(l1>1)/*z0y03+z0y02*/rt.z0y03=min(rt.z0y03,ls.z0y03+rs.z0y02+SUM);
	/*z0y03+z0y03不合法*/
}
void buildtree(int rt,int l,int r)
{
	if(l==r)
	  {
	  	T[rt].z1y1=zong[l];
	  	return;
	  }
	int m=(l+r>>1);
	buildtree(rt<<1,l,m);
	buildtree(rt<<1|1,m+1,r);
	pushup(T[rt],T[rt<<1],T[rt<<1|1],m,m-l+1,r-m);
}
void update(int p,int v,int rt,int l,int r)
{
	if(l==r)
	  {
	  	zong[p]=v;
	  	T[rt].z1y1=v;
	  	return;
	  }
	int m=(l+r>>1);
	if(p<=m) update(p,v,rt<<1,l,m);
	else update(p,v,rt<<1|1,m+1,r);
	pushup(T[rt],T[rt<<1],T[rt<<1|1],m,m-l+1,r-m);
}
void update(int p,int rt,int l,int r)
{
	if(l==r) return;
	int m=(l+r>>1);
	if(p<=m) update(p,rt<<1,l,m);
	else update(p,rt<<1|1,m+1,r);
	pushup(T[rt],T[rt<<1],T[rt<<1|1],m,m-l+1,r-m);
}
Node query(int ql,int qr,int rt,int l,int r)
{
    if(ql<=l && r<=qr) return T[rt];
    int m=(l+r>>1);
    if(ql<=m && m<qr)
      {
        Node res;
        pushup(res,query(ql,qr,rt<<1,l,m),query(ql,qr,rt<<1|1,m+1,r),m,m-l+1,r-m);
        return res;
      }
    else if(ql<=m) return query(ql,qr,rt<<1,l,m);
    else return query(ql,qr,rt<<1|1,m+1,r);
}
int main()
{
//	freopen("bzoj3995.in","r",stdin);
//	freopen("bzoj3995.out","w",stdout);
	for(int i=1;i<=500000;++i);
	scanf("%d%d",&n,&m);
	for(int i=0;i<2;++i)
	  for(int j=1;j<n;++j)
	    scanf("%d",&heng[i][j]);
	for(int i=1;i<=n;++i)
	  scanf("%d",&zong[i]);
	buildtree(1,1,n);
//	printf("%d\n",query(1,3,1,1,n).z1y1);
//	printf("%d\n",query(1,3,1,1,n).z1y0);
//	printf("%d\n",query(1,3,1,1,n).z0y1);
//	printf("%d\n",query(1,3,1,1,n).z0y02);
//	printf("%d\n",query(1,3,1,1,n).z0y03);
	char op[3];
	int x1,y1,x2,y2,val;
	for(;m;--m)
	  {
	  	scanf("%s",op);
	  	if(op[0]=='C')
	  	  {
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
            if(y1==y2) update(y1,val,1,1,n);
            else
              {
                if(y1>y2) swap(y1,y2);
                heng[x1-1][y1]=val;
                update(y1,1,1,n);
                update(y2,1,1,n);
              }
          }
        else
          {
          	scanf("%d%d",&y1,&y2);
          	printf("%d\n",query(y1,y2,1,1,n).z1y1);
          }
	  }
	return 0;
}

转载于:https://www.cnblogs.com/autsky-jadek/p/4638048.html

内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值