bryce1010专题训练——树状数组

2023-02-19,,

Bryce1010模板
1、一维树状数组
https://vjudge.net/contest/239647#problem/A【HDU1556】

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN=1e5+10;
int n,c[MAXN<<1];



//表示二进制x的最末尾的一个1
int lowbit(int x)
{
    return x&(-x);
}


//区间求和
int getSum(int x)
{
    int ans=0;
    while(x<=n)
    {
        ans+=c[x];
        x+=lowbit(x);
    }
    return ans;
}

//更新节点
void update(int pos,int val)
{
    while(pos>0)
    {
        c[pos]+=val;
        pos-=lowbit(pos);
    }
}


int main()
{
    int a,b;
    while(cin>>n)
    {
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            cin>>a>>b;
            update(b,1);
            update(a-1,-1);
        }
        for(int i=1;i<n;i++)
            cout<<getSum(i)<<" ";
        cout<<getSum(n)<<endl;
    }
}


2、二维树状数组
https://vjudge.net/contest/239647#problem/B【POJ 2155】

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
#define ll long long

const int MAXN=1e3+123;
int c[MAXN][MAXN];
int n,q;
int lowbit(int x)
{
    return x&(-x);
}

void update(int posi,int posj,int val)
{
    int tmpj;
    while(posi<=n)
    {
        tmpj=posj;
        while(tmpj<=n)
        {
            c[posi][tmpj]+=val;
            tmpj+=lowbit(tmpj);
        }
        posi+=lowbit(posi);
    }
}

int getSum(int posi,int posj)
{
    int ans=0;
    int tmpj=posj;
    while(posi>0)
    {
        tmpj=posj;
        while(tmpj>0)
        {
            ans+=c[posi][tmpj];
            tmpj-=lowbit(tmpj);
        }
        posi-=lowbit(posi);
    }
    return ans;
}






int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {

        char ch;
        int x1,y1,x2,y2;
        int x,y;
        scanf("%d%d",&n,&q);
        memset(c,0,sizeof(c));
        while(q--)
        {
            getchar();
            scanf("%c",&ch);
            if(ch=='C')
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                update(x1,y1,1);
                update(x2+1,y1,1);
                update(x1,y2+1,1);
                update(x2+1,y2+1,1);
            }
            else
            {
                scanf("%d%d",&x,&y);
                //查询前k的和对2取模即可
                printf("%d\n",getSum(x,y)%2);
            }

        }
        if(t)printf("\n");
    }


    return 0;
}

3、树状数组求逆序数
https://blog.csdn.net/Fire_to_cheat_/article/details/81129609

#include<bits/stdc++.h>
using namespace std;
#define ll long long


const int MAXN=5e5+10;


ll sum[MAXN],n;
struct Node
{
    int id,digit;
    Node(){}
    Node(int i,int d):id(i),digit(d){}
}node[MAXN];


bool cmp(Node a,Node b)
{
    return a.digit<b.digit;
}

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

void update(ll pos,ll val)
{
    while(pos<=n)
    {
        sum[pos]+=val;
        pos+=lowbit(pos);
    }
}



ll getSum(ll x)
{
    ll ans=0;
    while(x>0)
    {
        ans+=sum[x];
        x-=lowbit(x);
    }
    return ans;
}



int main()
{
    while(~scanf("%d",&n))
    {
        if(n==0)break;
        int x;
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            node[i]=Node(i,x);
        }
        sort(node+1,node+n+1,cmp);
        memset(sum,0,sizeof(sum));
        ll cnt=0;
        for(int i=1;i<=n;i++)
        {
            update(node[i].id,1);
            cnt+=(i-getSum(node[i].id));
        }
        cout<<cnt<<endl;


    }
    return 0;

}