树状数组


/*
题目:
第一行输入n,接下来一行是n个数(要求实现单点修改前缀查询) 
第3行是m,接下来m行有两种操作:1.C x y   2.A x 0  
*/

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath> 

using namespace std;

int a[1010];
int tree[1010];
int n,m,x,y;
char ch; 

int build()
{
	int i,j;
	for (i=1;i<=n;i++)
		for (j=i;j>i-(i&(-i));j--)  //树状数组每一个单点管辖的区间:i-(i&(-i))+1~i 
		   tree[i]+=a[j];
	return 0;
}

int change(int x,int v)  //单点修改
{
	int i;
	for (i=x;i<=n;i+=i&(-i))  //单点修改会对之后的tree值有影响 
	   tree[i]+=v;
	return 0;
}

int ask(int x)  //前缀查询 
{
	int i,ans=0;
	for (i=x;i>0;i-=i&(-i))  //前缀查询当然要倒着来 
	   ans+=tree[i];
	printf("%d
",ans);
	return 0;
}

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	   scanf("%d",&a[i]);
	build();  //建立树状数组
	scanf("%d",&m);
	for (int i=1;i<=m;i++)
	{
	    cin>>ch>>x>>y;
	    if (ch=='C')
	       change(x,y);
	    else 
	       ask(x);
    }
	return 0; 
} 


/*
题目:
第一行输入n,接下来一行是n个数(要求实现区间修改单点查询) 
第3行是m,接下来m行有两种操作:1.C x y v   2.A x  
*/

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath> 

using namespace std;

int a[1010];
int tree[1010];
int n,m,x,y,v;
char ch; 

int build()
{
	int i,j;
	for (i=1;i<=n;i++)
	   for (j=i;j>i-(i&(-i));j--)
	      tree[i]+=a[j];
	return 0;
}

int change(int x,int y,int v)  //区间修改
{
	int i;
	for (i=x;i<=n;i+=i&(-i))
	   tree[i]+=v;
	for (i=y+1;i<=n;i+=i&(-i))
	   tree[i]-=v;
	return 0;
}

int ask(int x)  //单点查询 
{
	int i,ans=0;
	for (i=x;i>0;i-=i&(-i))
	   ans+=tree[i];
	printf("%d
",ans);
	return 0;
}

int main()
{
	scanf("%d",&n);
	int num=0;
	for (int i=1;i<=n;i++)
	{
	   int now;
	   scanf("%d",&now); //使用差分的思想 
	   a[i]=now-num;
	   num=now; 
    }
	build();
	scanf("%d",&m);
	for (int i=1;i<=m;i++)
	{
	    cin>>ch;
	    if (ch=='C')
	    {
	       scanf("%d%d%d",&x,&y,&v);
		   change(x,y,v);
	    }
	    else 
	    {
	       scanf("%d",&x);
		   ask(x);
	    }
    }
	return 0; 
} 



原文地址:https://www.cnblogs.com/wutongtong3117/p/7673659.html