zoukankan      html  css  js  c++  java
  • 树状数组学习笔记

    树状数组模版
    int lowbit(int x)
     {
         return x&(-x);
     }
     
     void add(int pos,int val)////如果要把a[i]增加v,可以通过调用如下函数实现
     {
         while(pos <= MAXN)
         {
             tree[pos] += val;
             pos += lowbit(pos);//pos+lowbit(x)可以理解变成了x的父亲
         }
     }
     
     int read(int x)//前x项和
     {
         int s=0;
         while(x>0)
         {
             s += tree[x];
             x -= lowbit(x);//x-lowbit(x)可以理解成变成了x的兄弟
         }
         return s;
     }

    树状数组区间求和 poj-2352-Stars

    题意:一个“*”的层次是这样定义的,处于该“*”的下面和左面的范围内的“*”的个数即为该“*”的层次。题目要求处于0到n-1层次的“*”数目各有几个。

    分析:由于“*”的坐标已经按Y递增的顺序排列好,对于具有相同Y坐标的“*”,又按其X坐标排序,故可充分利用这一输入特点,直接运用树状数组进行求解。

     

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAXN 32050
    using namespace std;
    int tree[MAXN];
    int ans[MAXN];
    int lowbit(int x){
        return x&-x;
    }
    void add(int k,int num){
        while(k<MAXN){
            tree[k]+=num;
            k+=lowbit(k);
        }//当k=0时,会造成死循环
    }
    int read(int k){
        int s=0;
        while(k){
            s+=tree[k];
            k-=lowbit(k);
        }
        return s;
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n)){
            int x,y;
            memset(ans,0,sizeof(ans));
            for(int i=0;i<n;i++){
                scanf("%d%d",&x,&y);
                ans[read(x+1)]++;
                add(x+1,1);
            }
            for(int i=0;i<n;i++)printf("%d\n",ans[i]);
        }
        return 0;
    }

    树状数组求第k大数,相等于求第k=n-k+1小数

    poj--The k-th Largest Group

    题意:猫有很多,数不清,所以将它分组,一开始每只猫一组,操作为0时,表示把i,j组猫合并成新的一组,操作为1时,表示查询第k大组猫的个数

    分析:猫的合并用并查集 ,动态更新第K值用树状数组。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAXN 200050
    using namespace std;
    int n,m;
    int num;
    int tree[MAXN],fa[MAXN];
    int rank[MAXN];集合x的大小为rank[x]
    int lowbit(int x){
        return x&-x;
    }
    void add(int pos,int num){
        while(pos<=n){
            tree[pos]+=num;
            pos+=lowbit(pos);
        }
    }
    int read(int p){
        int s=0;
        while(p){
            s+=tree[p];
            p-=lowbit(p);
        }
        return s;
    }
    int find(int x){
       if(x!=fa[x]){
        fa[x]=find(fa[x]);
       }
       return fa[x];
    }//这种查询比return x==fa[x]?x:find(fa[x]);要快,如果采用注释的并查集会超时
    void init(int n){
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=n;i++)rank[i]=1;
        add(1,n);//初始状态值为1的有n个,(用线段树的思想理解就是第1-r这个区间都有1个值)
    }
    int find_kth(int k){
        int l=1,r=n;
        while(l<=r){
            int mid=(l+r)>>1;
            if(read(mid)>=k)r=mid-1;
            else l=mid+1;
        }
        return l;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)==2){
    //        scanf("%d%d",&n,&m);
            init(n);
            num=n;
            for(int i=0;i<m;i++){
                int cas;
                scanf("%d",&cas);
                if(!cas){
                    int a,b;
                    scanf("%d%d",&a,&b);
                    int x=find(a);
                    int y=find(b);
                    if(x==y)continue;
                    add(rank[x],-1);
                    add(rank[y],-1);
                    add(rank[y]=rank[x]+rank[y],1);
                    fa[x]=y;
                    num--;
                }
                else{
                    int k;
                    scanf("%d",&k);
                    k=num-k+1;
                    printf("%d\n",find_kth(k));
                }
            }
        }
        return 0;
    }

     

  • 相关阅读:
    大数据测试2
    大数据测试3
    CROSS APPLY和 OUTER APPLY 区别详解
    SQL中的escape的用法
    Sql Server参数化查询之where in和like实现详解
    多行文本框换行符处理
    Cross Apply的用法
    交叉连接Cross Join的用法
    统计字符串中某个字符的个数
    JOIN用法
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2635291.html
Copyright © 2011-2022 走看看