2017年8月16日训练日记

       如昨天计划,今天补了补昨天的题,感觉那些题目都是可以做的题目,可做的结果却不理想。然后今天上午老师还开了个会,讲到很重要的一个思想就是“一遍过”,这点对我来说是有些感悟的,不止ACM大学里学的东西都是如此,内容多且复杂,哪有那么多时间再学一遍?想要有一个好的掌握,就是一遍就掌握好他。如果一直反反复复,马马虎虎是浪费时间又掌握不好的。

       今天剩余时间在看树状数组资料,简单说一下树状数组,先不提其背后的位运算原理:

       int a[M],tree[M] ,sum[M];假设要将a数组转化为树状数组tree,sum是a数组的前缀和数组;

       树状数组就是为了提高运算效率的一种数据结构。这里运算有两种:

       1.修改第i个元素(a[i])的值。2.求从a[i]到a[j]的和。

       数组tree与a的关系:

       tree[i]=a[xx]+.....+a[i];   xx=i-[i&(-i)]+1;  lowbit(i)=i&(-i); 这里lowbit(i)表示i的二进制形式中最低位1的值。也就是lowbit(i) 表示i的二进制数表示形式留下最右边的1其余为取0得到的数

       a[i]∈c[i],tree[i=i+lowbit(i)],tree[i=i+lowbit(i)]...

       数组sum与tree的关系:

       sum[i]=tree[i]+tree[i=i-lowbit(i)]+tree[i=i-lowbit(i)]+......

int lowbit(int i)
{
    return i&(-i);
}
void add(int i,int v)  //元素a[i]增加v,n是元素的个数
{
    while(i<=n)
    {
        tree[i]+=v;
        i+=lowbit(i);
    }
}
int sum(int i) //相当于求sum[i]
{
    int res=0;
    while(i>0)
    {
        res+=tree[i];
        i-=lowbit(i);
    }
}

        树状数组的最基本功能就是求比某点 xi小(大)的点的个数,或者求数列的逆序数

memset(tree,0,sizeof(tree));
    long long ans=0;
    for(int i=0;i<k;i++)//k是元素个数,MAXN是元素最大值
    {  
        ans += sum(MAXN)-sum(a[i]);//累加逆序
        add(a[i],1);
    }
    printf("%I64d\n",ans);


          树状数组的内容再有理解会再补全。

      还有3天看资料时间,树状数组要争取速度,别时间分配不好线段树没看好,明天可以继续看树状数组,然后后天保证看看线段树的资料,如果还有时间就看情况分配吧


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值