写在前面:
关于原码,反码,补码:
正数:
原 == 反 ==补
负数:
原码略;
反码:第一位(符号位)不变,其他位取反;
补码:反码+1;
举个栗子:-10
原码:10001010;
反码:11110101;
补码:11110110;
树状数组:
ccs:树状数组,顾名思义,就是橡树一样的数组…
看这张图就一目了然了。
两个数组:
a[i]储存原序列;
c[i]树状数组;
c[1]存第一个数(如图),
c[2]存前两个数的和,
c[3]存第三个数,
c[4]存前四个数的和...以此类推。
树状数组储存方式独特,其中储存的和的个数为其lowbit值。
举个栗子:
c[1]中存了1个数,lowbit(1)=1;
c[2]中存了2个数,lowbit(2)=2;
c[4]中存了4个数,lowbit(4)=4;
而lowbit怎么算呢?(先逃)
树状数组主要包括三个函数
first. 求lowbit值
int lowbit(int x)
{
return x&(-x);
}
second.给第x个数加k
void update(int x,int k)
{
while(x<=n)
{
c[x]+=k;
x+=lowbit(x);
}
}
third.查询区间和
int getsum(int x)
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
(手动模拟一下就知道了)
题目
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某一个数加上x
2.求出某区间每一个数的和
输入格式
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3个整数,表示一个操作,具体如下:
操作1: 格式:1 x k 含义:将第x个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
输出格式
输出包含若干行整数,即为所有操作2的结果。
#include<iostream>
using namespace std;
int n,m;
int c[510000];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int k)//对第x个数加k
{
while(x<=n)
{
c[x]+=k;
x+=lowbit(x);
}
}
int getsum(int x)//求前x项的和
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int a;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a;
update(i,a);//建立树状数组
}
int x,k,z;
for(int i=1;i<=m;i++)
{
cin>>z>>x>>k;
if(z==1)update(x,k);
if(z==2)
{
int u=getsum(k);
int v=getsum(x-1);
cout<<u-v<<endl;
}
}
}
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数数加上x
2.求出某一个数的值
输入格式
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含2或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x 含义:输出第x个数的值
输出格式
输出包含若干行整数,即为所有操作2的结果。
#include<iostream>
using namespace std;
int n,m;
int c[510000],c2[510000];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int k)
{
while(x<=n)
{
c[x]+=k;
x+=lowbit(x);
}
}
int getsum(int x)
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int a,sum=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a;
update(i,a);
sum+=a;
c2[i]=sum;//直接用前缀和存原树状数组
}
int x,y,z;
for(int i=1;i<=m;i++)
{
cin>>a;
if(a==1)
{
cin>>x>>y>>z;
update(x,z);
update(y+1,-z);
}
if(a==2)
{
cin>>x;
cout<<getsum(x)-c2[x-1]<<endl;
}
}
}
以上,有错误之处欢迎指出~