蒟蒻学亿棵线段树

一、线段树简介

线段树是一种适用于维护区间信息的数据结构,可以在 O( l o g N logN logN) 的时间复杂度内实现单点修改、区间修改、区间查询等操作。(利用二叉堆思想)

二、代码实现(以实现区间和为例)

1、建树

递归分割,末端赋值,回溯合并
数组空间 2 ⌈ l o g 2 n ⌉ + 1 + 1 {2}^{\lceil{log_2^n}\rceil+1}+1 2log2n+1+1
一般来说数组开4N

// s,t指当前区间 p指当前序号
void build(int s,int t,int p){
	if(s==t){
		d[p]=a[s];
		return;
	}
	else{
		int m=s+((t-s)>>1);
		//与 m=(t+s)>>1 几乎等价,但上式可以防止计算过程中产生溢出
		build(s,m,p*2);
		build(m+1,t,p*2+1);
		d[p]=d[p*2]+d[p*2+1]; //更新
	}
}

2、LAZY TAG 懒标记

Tip: 极大区间实质上是被包含于查询区间 [L,R] 的最简区间 [S,T],此 [S,T] 区间之上的区间就超出了区间 [L,R] 的范围,其下的小区间又显然没有上面的大区间优。
在更新区间(如区间整体加减)时,我们会找到几个极大区间(区间数在 O( l o g N logN logN) 以内),因为不想将极大区间麾下的所有小区间全部更新(影响时间复杂度),所以用一种懒标记,这种标记存放于已经修改过值的节点,当有需求向下分割时再进行懒标记的下放(叶节点无需再次下放)

3、区间修改

// l,r指修改区间
void update(int l,int r,int c,int s,int t,int p){
	if(l<=s&&t<=r){
		//极大区间
		d[p]+=(t-s+1)*c;
		b[p]+=c;
		return;
	}
	else{
		int m=s+((t-s)>>1);
		if(b[p]&&s!=t){
			//非叶节点下放懒标记
			d[p*2]+=b[p]*(m-s+1);
			d[p*2+1]+=b[p]*(t-m);
			b[p*2]+=b[p];
			b[p*2+1]+=b[p];
			b[p]=0;
		}
		if(l<=m) update(l,r,c,s,m,p*2);
		if(m+1<=r) update(l,r,c,m+1,t,p*2+1);
		d[p]=d[p*2]+d[p*2+1]; //更新
	}
}

4、区间查询

typedef long long ll;
ll getsum(int l,int r,int s,int t,int p){
	if(l<=s&&t<=r) return d[p];
	int m=s+((t-s)>>1);
	//有需求向下分割,下放懒标记
	if(b[p]){
		d[p*2]+=b[p]*(m-s+1);
		d[p*2+1]+=b[p]*(t-m);
		b[p*2]+=b[p];
		b[p*2+1]+=b[p];		
		b[p]=0;
	}
	ll sum=0;
	if(l<=m) sum+=getsum(l,r,s,m,p*2);
	if(m+1<=r) sum+=getsum(l,r,m+1,t,p*2+1);
	return sum;
}

5、一棵刚出炉的线段树

代码相关题目:P3372 【模板】线段树 1

#include<bits/stdc++.h>

using namespace std;

const int N=1e5+5;
typedef long long ll;

int n,q;
ll a[N],d[4*N],b[4*N];

void build(int s,int t,int p){
	if(s==t){
		d[p]=a[s];
		return;
	}
	else{
		int m=s+((t-s)>>1);
		build(s,m,p*2);
		build(m+1,t,p*2+1);
		d[p]=d[p*2]+d[p*2+1];
	}
}

void update(int l,int r,int c,int s,int t,int p){
	if(l<=s&&t<=r){
		d[p]+=(t-s+1)*c;
		b[p]+=c;
		return;
	}
	else{
		int m=s+((t-s)>>1);
		if(b[p]&&s!=t){
			d[p*2]+=b[p]*(m-s+1);
			d[p*2+1]+=b[p]*(t-m);
			b[p*2]+=b[p];
			b[p*2+1]+=b[p];
			b[p]=0;
		}
		if(l<=m) update(l,r,c,s,m,p*2);
		if(m+1<=r) update(l,r,c,m+1,t,p*2+1);
		d[p]=d[p*2]+d[p*2+1];
	}
}

ll getsum(int l,int r,int s,int t,int p){
	if(l<=s&&t<=r){
		return d[p];
	}
	int m=s+((t-s)>>1);
	if(b[p]){
		d[p*2]+=b[p]*(m-s+1);
		d[p*2+1]+=b[p]*(t-m);
		b[p*2]+=b[p];
		b[p*2+1]+=b[p];		
		b[p]=0;
	}
	ll sum=0;
	if(l<=m) sum+=getsum(l,r,s,m,p*2);
	if(m+1<=r) sum+=getsum(l,r,m+1,t,p*2+1);
	return sum;
}

int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build(1,n,1);
	for(int i=1;i<=q;i++){
		int type;
		scanf("%d",&type);
		if(type==1){
			int x,y,k;
			scanf("%d%d%d",&x,&y,&k);
			update(x,y,k,1,n,1);
		}
		else{
			int x,y;
			scanf("%d%d",&x,&y);
			cout<<getsum(x,y,1,n,1)<<endl;
		}
	} 
	return 0;
}
### 关于ArcGIS License Server无法启动的解决方案 当遇到ArcGIS License Server无法启动的情况,可以从以下几个方面排查并解决问题: #### 1. **检查网络配置** 确保License Server所在的计算机能够被其他客户端正常访问。如果是在局域网环境中部署了ArcGIS Server Local,则需要确认该环境下的网络设置是否允许远程连接AO组件[^1]。 #### 2. **验证服务状态** 检查ArcGIS Server Object Manager (SOM) 的运行情况。通常情况下,在Host SOM机器上需将此服务更改为由本地系统账户登录,并重启相关服务来恢复其正常工作流程[^2]。 #### 3. **审查日志文件** 查看ArcGIS License Manager的日志记录,寻找任何可能指示错误原因的信息。这些日志可以帮助识别具体是什么阻止了许可服务器的成功初始化。 #### 4. **权限问题** 确认用于启动ArcGIS License Server的服务账号具有足够的权限执行所需操作。这包括但不限于读取/写入特定目录的权利以及与其他必要进程通信的能力。 #### 5. **软件版本兼容性** 保证所使用的ArcGIS产品及其依赖项之间存在良好的版本匹配度。不一致可能会导致意外行为完全失败激活license server的功能。 #### 示例代码片段:修改服务登录身份 以下是更改Windows服务登录凭据的一个简单PowerShell脚本例子: ```powershell $serviceName = "ArcGISServerObjectManager" $newUsername = ".\LocalSystemUser" # 替换为实际用户名 $newPassword = ConvertTo-SecureString "" -AsPlainText -Force Set-Service -Name $serviceName -StartupType Automatic New-ServiceCredential -ServiceName $serviceName -Account $newUsername -Password $newPassword Restart-Service -Name $serviceName ``` 上述脚本仅作为示范用途,请依据实际情况调整参数值后再实施。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值