Phone Network(小米邀请赛)

Phone Network

题目大意

有一个长度为 n 的数组,里面有每个值为 1–m之间且每个数出现的次数至少为1.问分别求出每个包含从 1–i 的最短区间的长度。

解题思路

这个线段是真的是涨姿势呀!!!
题解
在构建线段树之前我们分别记录每种节点出现的位置。
这样我们构建线段树的时候,从第一种节点开始构建,线段树记录每个节点到 包含 1–i 号节点的最短距离。ma记录的包含这个区间的最远位置,如果我们查询每个节点的位置是浮现它对应的ma已经大于当前的坐标了,就不用更新了。
比如说 从 1 3 2
记录完以后 三个数对应的 ma 都是 3 3 3 (2的pos 是3)
再更新的时候 pos 值时 2 所以用更新了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mx=200100;
const int inf=100010000;
int n,m;
struct node{
// ma 为距离其最远的右端点	
	int ma;
// 记录答案	
	int ans;
	int lazy;
	int l,r;
}a[mx<<2]; 
vector<int> ve[mx];

void build(int x,int l,int r){
	a[x].ans=inf;
	a[x].ma=0;
	a[x].lazy=0;
	a[x].l=l;
	a[x].r=r;
	if(l==r){
		return ;
	}
	int mid=l+r>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
}

void up_down(int x){
	int k=a[x].lazy;
	if(k==0) return ;
	a[x<<1].lazy=k;
	a[x<<1|1].lazy=k;
	
	a[x<<1].ma=k;
	a[x<<1|1].ma=k;
	
	a[x<<1].ans=k-a[x<<1].r+1;
	a[x<<1|1].ans=k-a[x<<1|1].r+1;
	a[x].lazy=0;
	return ;
}

int query(int x,int ql,int qr){
	if(a[x].ma>=qr) return -1;
	if(a[x].l>qr||a[x].r<ql)
		return -1;
//	这里为什么不能是  a[x].l>=ql&&a[x].r 呢?
// 因为我们需要知道是最靠近的 x 这个节点的
// 按照这样找的是这个区间内最左短的
// 有可能这个区间中间的一部分也不是可以的
// 所以这里要找到 的是点 
	if(a[x].l==a[x].r){
		return a[x].l;
	}
	up_down(x); 
	int	ans=query(x<<1|1,ql,qr);
	if(ans==-1) ans=query(x<<1,ql,qr);
	return ans;
}

void up(int x,int l,int r,int k){
	if(l>r) return;
	if(a[x].l>r||a[x].r<l) return;
	if(a[x].l>=l&&a[x].r<=r){
		a[x].ans=k-a[x].r+1;
		a[x].ma=k;
		a[x].lazy=k;
		return ;    
	}
	up_down(x);
	up(x<<1,l,r,k);
	up(x<<1|1,l,r,k);
	a[x].ans=min(a[x<<1].ans,a[x<<1|1].ans);
	a[x].ma=min(a[x<<1].ma,a[x<<1|1].ma);
}
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for(int i=1,x;i<=n;i++){
		cin>>x;
		ve[x].push_back(i);
	} 
	build(1,1,n);
	for(int i=1,pos,per;i<=m;i++){
		per=0;
		for(int p:ve[i]){
// 查找以p为右端点 最靠近且满足情况的左端点。			
			pos=query(1,per+1,p);
			if(pos!=-1) up(1,per+1,pos,p);
			per=p;
		}
// 这里 x 的城市覆盖的最广才到	ve[i].back
// 所以我们需要把后面的全部覆盖成最大值,防止
// 后面的部分影响前面的。	
		if(ve[i].back()<n){
			up(1,ve[i].back()+1,n,inf);
		}
		cout<<a[1].ans<<" \n"[i==m];
	}
	return 0;
} 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值