码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组及其他特别简单的扩展

时间:2018-03-02 20:50:30      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:false   str   求逆   sync   告诉   pen   nod   while   离散化   

度娘真是个好东西

树状数组


struct node
{
    int len;
    int tree[1000100];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void updata(int x,int value)
    {
        while(x<=len)
        {
            tree[x]+=value;
            x+=lowbit(x);
        }
    }
    int sum(int x)
    {
        int ans=0;
        while(x>0)
        {
            ans+=tree[x];
            x-=lowbit(x);
        }
        return ans;
    }
    int check(int x,int y)
    {
        return sum(y)-sum(x-1);
    } 
};

树状数组可以快速的查询区间和插叙两次

所以我们就可以将被求和换成其他意义的数组,完成不同的任务

比如说区间修改和单点查询(注意这两个是同时存在的),还比如求逆序对

上题

逆序对

单点查询和区间修改

对于逆序对这道题,在桶拍上用树状数组,还需要进行离散化。如果数据范围是int以外,那直接开桶是要炸的 树状数组就是个辣鸡

#include<iostream>
#include<algorithm>
using namespace std;
struct haha
{
    int val;
    int hao;
};
bool compare(haha a,haha b)
{
    return a.val>b.val;
}
haha in[41000];
struct node
{
    int tree[41000];
    int num;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void updata(int i,int value)
    {
        while(i<=num)
        {
            tree[i]+=value;
            i+=lowbit(i);
        }
        return ;
    }
    int sum(int x)
    {
        int ans=0;
        if(x)
            while(x>0)
            {
                ans+=tree[x];
                x-=lowbit(x);
            }
        return ans;
    }
    int check(int x,int y) 
    {
        return sum(y)-sum(x-1);
    }
};
node bit;
int cym[41000],da=0,h=0;
int main()
{
    cin.sync_with_stdio(false);//没错,我就是懒
    /*freopen("testdata.in","r",stdin);
    freopen("testdata.out","w",stdout);*/
    int n;
    cin>>n;
    bit.num=n;
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        cin>>in[i].val;
        in[i].hao=i;
    } 
    sort(in+1,in+n+1,compare);
    for(int i=1;i<=n;i++)
    {
        if(h!=in[i].val)
        {
            da++;//第几大
            h=in[i].val;//如果有重复的就是一样大
        }
        cym[in[i].hao]=da;
    }
    for(int i=1;i<=n;i++)//顺序插入,为什么??就不告诉你,自己想去吧
    {
        ans+=bit.check(0,cym[i]-1);
        bit.updata(cym[i],1);
    }
    cout<<ans;
}

区间修改和单点查询的话就是利用差分数组。

#include<iostream>
#include<cstring>
using namespace std;
struct node
{
    int len;
    int tree[500100];
    node(){len=0;memset(tree,0,sizeof(tree));}
    int lowbit(int x)
    {
        return x&(-x);
    }
    void updata(int pos,int value)
    {
        while(pos<=len)
        {
            tree[pos]+=value;
            pos+=lowbit(pos);
        }
    }
    int sum(int pos)
    {
        if(!pos)
            return 0;
        int pass=0;
        while(pos>0)
        {
            pass+=tree[pos];
            pos-=lowbit(pos);
        }
        return pass;
    }
    int check(int left,int right)
    {
        return sum(right)-sum(left-1);
    }
};
node bit;
int main()
{
    cin.sync_with_stdio(false);
    int n,m;
    cin>>n>>m;
    int a,b,c,d=0;
    bit.len=n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        bit.updata(i,a-d);
        d=a;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>a;
        if(a==1)
        {
            cin>>b>>c>>d;
            bit.updata(b,d);
            bit.updata(c+1,-1*d);
        }
        if(a==2)
        {
            cin>>b;
            cout<<bit.check(1,b)<<endl;
        }
    }
}

树状数组及其他特别简单的扩展

标签:false   str   求逆   sync   告诉   pen   nod   while   离散化   

原文地址:https://www.cnblogs.com/Lance1ot/p/8494597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!