2017年8月16日训练日记

来源:互联网 发布:淘宝玉石店铺推荐 编辑:程序博客网 时间:2024/06/15 09:29

       如昨天计划,今天补了补昨天的题,感觉那些题目都是可以做的题目,可做的结果却不理想。然后今天上午老师还开了个会,讲到很重要的一个思想就是“一遍过”,这点对我来说是有些感悟的,不止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天看资料时间,树状数组要争取速度,别时间分配不好线段树没看好,明天可以继续看树状数组,然后后天保证看看线段树的资料,如果还有时间就看情况分配吧


原创粉丝点击