lowbit运算
lowbit(x) = x & (-x) //取x的二进制最右边的1和它右边的所有0
树状数组及其应用
//getSum函数返回前x个整数之和
int getSum(int x){
int sum = 0;
for(int i = x;i > 0 ;i -= lowbit(i)){
sum += c[i];
}
return sum;//返回和
}
//update函数将第x个整数加上v
void update(int x,int v){
for(int i =x;i <= N;i += lowbit(i)){
c[i] += v;//c[i]加上v,然后让c[i+lowbit(i)]加上v
}
}
给定一个有N个正整数的序列A,对序列中的每个数,求出序列中它左边比它小的数的个数
#include<cstdio>
#include<cstring>
const int maxn = 100010;
#define lowbit(i) ((i)&(-i))
int c[maxn];
void update(int x,int v){
for(int i = x;i < maxn;i += lowbit(i)){
c[i] += v;
}
}
int getSum(int x){
int sum = 0;
for(int i = x;i > 0;i -= lowbit(i)){
sum += c[i];
}
return sum;
}
int main(){
int n,x;
scanf("%d",&n);
memset(c,0,sizeof(c));
for(int i = 0;i < n;i++){
scanf("%d",&x);
update(x,1);
printf("%d",getSum(x - 1));
if(i < n-1) printf(" ");
}
printf("\n");
return 0;
}
离散化代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100010;
#define lowbit(i) ((i)&(-i))
struct Node{
int val;
int pos;
}temp[maxn];
int A[maxn];
int c[maxn];
//update函数将第x个整数加上v
void update(int x,int v){
for(int i = x;i < maxn;i++){
c[i] +=v;
}
}
//getSum函数返回前x个元素的和
int getSum(int x){
int sum = 0;
for(int i = x;i > 0;i -= lowbit(i)){
sum += c[i];
}
return sum;
}
//按val从小到大排序
bool cmp(Node a,Node b){
return a.val < b.val;
}
int main(){
int n;
scanf("%d",&n);
memset(c,0,sizeof(c));
for(int i = 0;i < n;i++){
scanf("%d",&temp[i].val);
temp[i].pos = i;
}
//离散化
sort(temp,temp + n,cmp);
for(int i = 0;i < n;i++){
if(i == 0||temp[i].val != temp[i -1].val){
A[temp[i].pos] = 1 + i;
}else{
A[temp[i].pos] = A[temp[i - 1].pos];
}
}
//正式进入更新和求和操作
for(int i = 0;i < n;i++){
update(A[i],1);
printf("%d\n",getSum(A[i]-1));
}
return 0;
}
求解数列第k大
//求序列元素第k大
int findKthElement(int K){
int l = 1, r = maxn,mid;
while(l < r){
mid = (l + r)/2;
if(getSum(mid) >= K) r = mid;
else l = mid + 1;//所求位置大于mid
}
return l;
}
求子矩阵和的getsum和update实现:
int c[maxn][maxn];
//二维update函数位置为(x,y)的整数加上v
void update(int x,int y,int v){
for(int i =x;i < maxn;i += lowbit(i)){
for(int j = y;j < maxn;j +=lowbit(j)){
c[i][j] += v;
}
}
}
//二维getSum函数返回(1,1)到(x,y)的子矩阵的和
int getSum(int x,int y){
int sum = 0;
for(int i = x;i > 0;i -= lowbit(i)){
for(itn i = y;i > 0;i -= lowbit(j)){
sum += c[i][j];
}
}
return sum;
}
区间更新,单点查询
//getSum函数返回第x个整数的值
int getSum(int x){
int sum = 0;//记录和
for(int i = x;i < maxn;i +=lowbit(i)){
sum += c[i];//累计c[i]
}
return sum;
}
//update函数将前x个元素加上v
void update(int x,int v){
for(int i = x;i > 0;i -= lowbit(i)){
c[i] += v;//让c[i]加上v
}
}