zoukankan      html  css  js  c++  java
  • 树状数组复习

    树状数组复习

    1. 楼兰图腾: 区间查询

    • 对于 v : 统计左侧有多少个大于x的,右侧有多少个大于x的, 两者相乘
    • 对于 ^ : 统计左侧有多少个小于x的,右侧有多少个小于x的, 两者相乘

    对于每一个加入的数,相当于给那个值的位置+1

    每一次统计:[1,v] [v,+inf] 个数

    
    
    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N = 2e5 + 5;
    
    int n,temp;
    int arr[N];
    
    
    inline int lowbit(int x){
        return x & -x;
    }
    
    inline void add(int pos,int n,int val){
        while(pos <= n){
            arr[pos] += val;
            pos += lowbit(pos);
        }
    }
    
    inline int query(int pos){
        int ans = 0;
        while(pos >= 1){
            ans += arr[pos];
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    
    
    
    int main(){
        ll ans1 = 0;
        ll ans2 = 0;
        scanf("%d",&n);
        
        
        for(int i = 1; i <= n; ++i){
            scanf("%d",&temp);
            add(temp,n,1);
            ll a = query(temp-1); // 之前有多少个小于的
            ll b = (temp-1) - a;  // 之后有多少个小于的
            
            ll c = query(n) - query(temp); // 之前有多少个大于的
            ll d = (n-temp) - c;    // 之后有多少个大于的
            
            ans2 += a*b;
            ans1 += c*d;
        }
        
        printf("%lld %lld",ans1,ans2);
        return 0;
    }
    
    

    2. 谜一样的牛: 二分+区间查询(前缀动态第k大)

    从后向前遍历,不断赋予身高;第i头牛前面有k头牛比它高的时候,表明当前这一头牛是剩余可选身高里第k+1高的牛

    需要在[1,n]区间内动态查询第k+1大值;一开始所有数都存在,中途修改某一个值不存在

    查询方法: 二分法 + 树状数组区间和

    二分右端点,查询第一个区间和为[k+1]的右端点

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e5+10;
    
    int arr[N];
    int temp[N];
    
    int n;
    
    inline int lowbit(int x){
        return x & -x;
    }
    
    inline void add(int pos,int n,int v){ // 某个数+1
        while(pos <= n){
            arr[pos] += v;
            pos += lowbit(pos);
        }
    }
    
    inline int query(int pos){ // 获取小于等于某个数的个数
        int ans = 0;
        while(pos >= 1){
            ans += arr[pos];
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    inline int find_pos(int val){
        int l = 1, r = n;
        int ans = -1;
        while( l <= r ){
            int mid = (l+r)>>1;
            if(query(mid) >= val){
                ans = mid;
                r = mid-1;
            }else{
                l = mid+1;
            }
        }
        return ans;
    }
    
    
    int main(){
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i){
            add(i,n,1);
        }
        
        for(int i = 2; i <= n; ++i){
            scanf("%d",&temp[i]); 
        }
        
        for(int i = n; i >= 1; --i){
            temp[i] = find_pos(1+temp[i]);
            add(temp[i],n,-1);
        }
        int first = 1;
        for(int i = 1; i <= n; ++i){
            if(first)first = 0;else putchar('
    ');
            printf("%d",temp[i]);
        }
        return 0;
    }
    
    ---- suffer now and live the rest of your life as a champion ----
  • 相关阅读:
    csu1217: 奇数个的那个数
    小试SAS 判别分析
    bfs poj2965
    STL set常用操作
    csu1002 A+B(III)
    HDOJ 1002 的几种方法
    SQL知识积累
    CSV文件格式介绍
    ASP.net Web Form 知识积累
    C# 位域[flags] 枚举
  • 原文地址:https://www.cnblogs.com/popodynasty/p/14348016.html
Copyright © 2011-2022 走看看