【模板】单点修改,单点查询;区间修改,单点查询;区间修改,区间查询(树状数组,线段树)

单点修改,单点查询

例题

Luogu:P3374

Code

树状数组

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
using namespace std;
typedef long long ll;
inline int sread()
{
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return f*x; 
}
const int maxn=5e5+10;
int a[maxn],ops,x,y,k,n,m,ans,c[maxn];
int lowbit(int x)
{
	return x&(-x);
}
void update(int x,int val)
{
	for(rg int i=x;i<=n;i+=lowbit(i)) c[i]+=val;
}
int getsum(int x)
{
	int sum=0;
	for(rg int i=x;i;i-=lowbit(i)) sum+=c[i];
	return sum;
}
int main()
{
	n=sread();	m=sread();
	for(rg int i=1;i<=n;++i)
	{
		a[i]=sread();
		update(i,a[i]);	
	}
	for(rg int i=1;i<=m;++i)
	{
		ops=sread();
		if(ops==1) 
		{
			x=sread();	k=sread();
			update(x,k);
		}
		else if(ops==2)
		{
			x=sread();	y=sread();
			ans=getsum(y)-getsum(x-1);
			printf("%d\n",ans);
		}
	} 
	return 0;
}

线段树

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define rg register
using namespace std;
inline int sread()
{
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
	return f*x;
}
const int maxn=500050;
struct segtreenode{
	int val;
}segtree[4*maxn];
int n,m,q,w,x,ans;
int a[maxn+10];

void make_tree(int rt,int al,int ar)
{
	if(al==ar)
	{
		segtree[rt].val=a[al]; return;
	}
	int mid=(al+ar)/2;
	make_tree(rt*2,al,mid);
	make_tree(rt*2+1,mid+1,ar);
	segtree[rt].val=segtree[rt*2].val+segtree[rt*2+1].val;
}
void szupdate(int rt,int al,int ar,int x,int val)
{
	if(al==ar)
	{
		if(al==x)	segtree[rt].val+=val;
		return; 
	}
	int mid=(al+ar)/2;
	if(x<=mid) szupdate(rt*2,al,mid,x,val);
	else szupdate(rt*2+1,mid+1,ar,x,val); 
	segtree[rt].val=segtree[rt*2].val+segtree[rt*2+1].val;
}
int szquery(int rt,int al,int ar,int ql,int qr)
{
	if(al>qr||ar<ql) return 0;
	if(ql<=al&&qr>=ar) return segtree[rt].val;
	int mid=(al+ar)/2;
	return (szquery(rt*2,al,mid,ql,qr)+szquery(rt*2+1,mid+1,ar,ql,qr));
}
int main()
{
	n=sread(); m=sread();
	for(rg int i=1;i<=n;++i)
		a[i]=sread();
	make_tree(1,1,n);
	for(rg int i=1;i<=m;++i)
	{
		q=sread(); x=sread(); w=sread();
		if(q==1) szupdate(1,1,n,x,w);	
		if(q==2)
		{
			ans=szquery(1,1,n,x,w);
			printf("%d\n",ans);
		}
	}
}

区间修改,单点查询

例题

Luogu:P3368

Acwing:一个简单的整数问题

Code

树状数组

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
using namespace std;
typedef long long ll;
inline int sread()
{
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return f*x; 
}
const int maxn=5e5+10;
int a[maxn],ops,x,y,k,n,m,ans,c[maxn];
int lowbit(int x)
{
	return x&(-x);
}
void update(int x,int val)
{
	for(rg int i=x;i<=n;i+=lowbit(i)) c[i]+=val;
}
int getsum(int x)
{
	int sum=0;
	for(rg int i=x;i;i-=lowbit(i)) sum+=c[i];
	return sum;
}
int main()
{
	n=sread();	m=sread();
	for(rg int i=1;i<=n;++i)
	{
		a[i]=sread();
	}
	for(rg int i=1;i<=m;++i)
	{
		ops=sread();
		if(ops==1) 
		{
			x=sread();	y=sread();	k=sread();
			update(x,k); update(y+1,(-1)*k);
		}
		else if(ops==2)
		{
			x=sread();
			ans=a[x]+getsum(x);
			printf("%d\n",ans);
		}
	} 
	return 0;
}

线段树

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
#define ll long long 
using namespace std;
inline int sread()
{
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return f*x; 
}
const int maxn=500050;
const int INF=0x7fffffff;
struct node{
	int val;int lazytag;
}segtree[4*maxn];
int a[maxn+10];
int minn(int a,int b)
{
	return a<b?a:b;
}

void make_tree(int rt,int al,int ar)
{
	segtree[rt].lazytag=0;
	if(al==ar)
	{
		segtree[rt].val=a[al]; return;
	}
	int mid=(al+ar)>>1;
	make_tree(2*rt,al,mid);
	make_tree(2*rt+1,mid+1,ar);
	segtree[rt].val=minn(segtree[2*rt].val,segtree[2*rt+1].val);
}

void pushdown(int rt,int al,int ar)
{
	if(al!=ar&&segtree[rt].lazytag!=0)
	{
		segtree[2*rt].val+=segtree[rt].lazytag;
		segtree[2*rt].lazytag+=segtree[rt].lazytag;
		segtree[2*rt+1].val+=segtree[rt].lazytag;
		segtree[2*rt+1].lazytag+=segtree[rt].lazytag;
		segtree[rt].lazytag=0;
	}
}

int szquery(int rt,int al,int ar,int ql,int qr)//a:被查询 q:查询 
{
	if(ql>ar||qr<al) return INF;
	if(al>=ql&&ar<=qr)
	{
		return segtree[rt].val;
	}
	pushdown(rt,al,ar);
	int mid=(al+ar)>>1;
	return minn(szquery(2*rt,al,mid,ql,qr),szquery(2*rt+1,mid+1,ar,ql,qr));
}

void szupdate(int rt,int al,int ar,int ql,int qr,int val)
{
	if(al>qr||ar<ql) return;
	if(ql<=al&&ar<=qr)
	{
		segtree[rt].val+=val;
		segtree[rt].lazytag+=val;
		return;
	}
	pushdown(rt,al,ar);
	int mid=(al+ar)>>1;
	szupdate(2*rt,al,mid,ql,qr,val);
	szupdate(2*rt+1,mid+1,ar,ql,qr,val);
	segtree[rt].val=minn(segtree[2*rt].val,segtree[2*rt+1].val);
}

int n,m;
int x,y,k,p;
int main()
{
	n=sread();m=sread();
	for(rg int i=1;i<=n;++i)
		a[i]=sread();
	make_tree(1,1,n);
	for(rg int i=1;i<=m;++i)
	{
		p=sread();
		if(p==2)
		{
			x=sread();
			printf("%d\n",szquery(1,1,n,x,x));
		}
		if(p==1)
		{
			x=sread();y=sread();k=sread();
			szupdate(1,1,n,x,y,k);
		}
	}
	return 0;
}

区间修改,区间查询

例题

Acwing:243.一个简单的整数问题2

Code

树状数组

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
using namespace std;
typedef long long ll;
inline ll sread()
{
	ll x=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return f*x; 
}
const ll maxn=5e5+10;
ll a[maxn],x,y,k,n,m,ans,c[3][maxn],sum[maxn];
char ops;
ll lowbit(ll x)
{
	return x&(-x);
}
void update(ll k,ll x,ll val)
{
	for(rg ll i=x;i<=n;i+=lowbit(i)) c[k][i]+=val;
}
ll getsum(ll k,ll x)
{
	ll sum=0;
	for(rg ll i=x;i;i-=lowbit(i)) sum+=c[k][i];
	return sum;
}
int main()
{
	n=sread();	m=sread();
	for(rg ll i=1;i<=n;++i)
	{
		a[i]=sread();
		sum[i]=sum[i-1]+a[i];
	}
	for(rg ll i=1;i<=m;++i)
	{
		cin>>ops;
		if(ops=='C') 
		{
			x=sread();	y=sread();	k=sread();
			update(1,x,k); update(1,y+1,(-1)*k);
			update(2,x,x*k);	update(2,y+1,(-1)*(y+1)*k);
		}
		else if(ops=='Q')
		{
			x=sread(); y=sread();
			ans=sum[y]+(y+1)*getsum(1,y)-getsum(2,y);
			ans-=sum[x-1]+x*getsum(1,x-1)-getsum(2,x-1); 
			printf("%lld\n",ans);
		}
	} 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
树状数组(Fenwick Tree)是一种用于高效处理区间修改单点查询数据结构。下面我将介绍如何使用树状数组实现区间修改单点查询。 首先,我们需要定义树状数组数据结构树状数组由一个数组和一组操作组成,其中数组用于存储数据,操作用于更新和查询数组中的值。 下面是一个示例的树状数组实现: ```python class FenwickTree: def __init__(self, n): self.size = n self.tree = [0] * (n + 1) def update(self, idx, delta): while idx <= self.size: self.tree[idx] += delta idx += idx & -idx def query(self, idx): res = 0 while idx > 0: res += self.tree[idx] idx -= idx & -idx return res def range_update(self, l, r, delta): self.update(l, delta) self.update(r + 1, -delta) def point_query(self, idx): return self.query(idx) ``` 在上面的代码中,我们定义了一个FenwickTree类,通过构造函数`__init__`来初始化树状数组,并使用`size`来表示数组的大小。`tree`数组用于存储数据。`update`方法用于更新指定位置的值,`query`方法用于查询指定位置之前的求和结果。`range_update`方法用于对指定区间进行修改,`point_query`方法用于查询单个位置的值。 下面是一个示例的使用场景: ```python # 示例使用 n = 10 tree = FenwickTree(n) # 区间修改 [2, 6] 的值加 3 tree.range_update(2, 6, 3) # 查询位置 5 的值 value = tree.point_query(5) print(value) ``` 在上面的示例中,我们创建了一个大小为10的树状数组,并对区间[2, 6]的值进行了修改,将其加3。然后,我们查询了位置5的值,结果为3。 希望以上内容能够帮助到你实现树状数组区间修改单点查询。如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值