集训8.21树状数组讲解

来源:互联网 发布:穿衣打扮 知乎 编辑:程序博客网 时间:2024/04/25 18:39

有点想家了。。。

树状数组的用途:单点更新,区间查询(如敌兵布阵)

                              区间更新,单点查询(如color the ball)

一维树状数组:

int lowbit(int x)
{
    return x&(-x);
}
long long sum(int i)
{
    long long res=0;//别忘赋值
    while(i>0)
    {
        res+=c[i];
        i-=lowbit(i);
    }

return res;
}
void add(int i,int sum)//对ci位置!!!上的数加sum
{
    while(i<=inf)//inf是c位置上能放的最大的数
    {
        c[i]+=sum;
        i+=lowbit(i);
    }
}
int main()
{
    memset(c,0,sizeof(c));//c树状数组
}

二维树状数组:

int lowbit(int x)
{
    return x&(-x);
}
long long sum(int x,int y)//求(1,1)到(x,y)所围城的矩形上的点代表的数的和
{
    long long res=0;
    for(;x>0;x-=lowbit(x))
    {
        for(int j=y;j>0;j-=lowbit(j))
        {
            res+=c[x][j];
        }
    }
    return res;
}
void add(int x,int y,int sum)//对c[x][y]位置上的数加sum
{
    for(;x<=maxx;x+=lowbit(s))//c的横坐标所能放的最大的数
    {
        for(int j=y;j<=maxy;j+=lowbit(j))//c的纵坐标所能放的最大的数
            c[x][j]+=sum;
    }
}
int main()
{
    memset(c,0,sizeof(c));
}

逆序数:逆序对的个数

如何求逆序数?

  1.  for(int i=1;i<=n;i++)  
  2.         {  
  3.             add(b[i],1); 
  4.             ans += sum(n)-sum(b[i]);  
  5.       }  

如何离散化

struct node
{
    int x,id;
};
node a[100];
int b[100];
bool cmp(node a,node b)
{
    return a.x<b.x;//开始离散化先排序!!!!!!!!!!!!!!!!!!
}
int main()
{
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].x;
        a[i].id=i;
    }
    sort(a+1,a+1+n,cmp);
    b[a[i].id]=i;
    for(i=2;i<=n;i++)
    {
        if(a[i].x!=a[i-1].x)
            b[a[i].id]=i;
        else
            b[a[i].id]=b[a[i-1].id;
    }
}

对于二维树状数组如何求(x1,y1)到(x2,y2)的和

int main()
{
    cin>>x1>>y1>>x2>>y2;
    if(x1>x2)
        swap(x1,x2);//二维数组保证左下到右上
        if(y1>y2)
        swap(y1,y2);
    x1++;y1++;x2++;y2++;
    sum(x2,y2)+sum(x1-1,y1-1)-sum(x2,y1-1)-sum(x1-1,y2);//画个矩形就明白了特别巧妙
}

二维数组输入(x,y)

add(x+1,y+1,num)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

二维数组可设一个a[100][100]来存放a[i][j]位置上的数是多少;

 

相对于一维树状数组染气球,二维数组也有类似的题,只不过是一维变化区间,二维变化矩形

一维 [l,r] add(l,1),add(r+1,-1) sum(i)就是地i个气球被染色总数

二维[x1,y1] [x2,y2]

                                  

  1.  add(x1,y1,1);  
  2.             add(x1,y2+1,1);  
  3.             add(x2+1,y1,1);  
  4.             add(x2+1,y2+1,1);  sum[x][y]就是该点的值

 

三维树状数组

 int sum(int x,int y,int z)
{
    int res=0;
    for(int i=x;i>0;i-=lowbit(i))
    {
        for(int j=y;j>0;j-=lowbit(j))
        {
            for(int k=z;k>0;k-=lowbit(k))
                res+=c[i][j][k];
        }
    }
    return res;
}
int add(int x,int y,int z,int num)
{
    for(int i=x;i<=maxx;i+=lowbit(i))
    {
        for(int j=y;j<=maxy;j+=lowbit(j))
        {
            for(int k=z;k<=maxz;k+=lowbit(k))
                c[i][j][k]+=num;
        }
    }
}