树状数组和线段树

线段树

主要解决两个问题:(其他问题可以转化)更新某一点的值;求区间值;时间按复杂度(logn)
原数组a[1] a[2] …a[n];
写成树状数组c:c[x]=(x-lowbit(x),x] 左开右闭;

笔记在这里插入图片描述
主要代码

const int N=?;
int tr[N];

int lowbit(int x){	return x&-x; 	}

void add(int x,int v){
	for(int i = x;i < N; i += lowbit(i))
		tr[i]+=v;
}

int sum(int x){
	int res = 0;
	for(int i = x;i > 0; i -= lowbit(i))
		res+=tr[i];
	return res;
}

线段树

两个基本操作:单点修改和区间查询。
四个核心函数:pushup:用子节点信息更新当前节点信息;build:在一段区间上初始化线段树;modify:单点修改;query:区间查询;
用数组存储线段树:x的父节点x>>1;x的左儿子:x<<1;x的右儿子x>>1|1.
核心代码:
在这里插入图片描述


const int N=100010;

int n,m;
int w[N];
struct Node{
	int l,r;
	int sum;
}tr[4*N];
void pushup(int u){
	tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void build(int u,int l,int r){
	if(l==r) 
		tr[u]={l,r,w[r]};
	else {
		tr[u]={l,r};
		int mid=l+r >>1;
		build(u<<1,l,mid),build(u<<1|1,mid+1,r);
		pushup(u);
	}
}
int query(int u,int l,int r){
	if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
	int sum=0;
	int mid=tr[u].l+tr[u].r >>1;
	if(l<=mid)
		sum=query(u<<1,l,r);//因为是第一个书  sum初始值0  可以省略+
	if(r>mid)
		sum+=query(u<<1|1,l ,r );
	return sum;
}
void modify(int u,int x,int v){
	if(tr[u].l==tr[u].r)
		tr[u].sum+=v;
	else{
		int mid=tr[u].l+tr[u].r >>1;
		if(x<=mid)
			modify(u<<1,x,v);
		else
			modify(u<<1|1,x,v);
		pushup(u);
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值