zoukankan      html  css  js  c++  java
  • HDU4417 线段树 + 离线处理

      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 , 线段树(或树状数组) + 离线处理

      最近看了几道线段树的题都是需要离线处理数据的,正好这块比较手生,就练练了。


       这道题主要的地方就是离线处理数据,具体想法:

      ① 先把所有位置的高度都存下来,然后排序,注意保存下标;

      ② 把所有询问存下来,然后按照询问的高度进行排序,同注意保存下标;

      ③ 对于排序后的每次询问的处理:由于每个位置的高度都已经存了下来并且进行了排序,所以可以按照顺序将每个点插入到线段树的对应位置(保存的下标),并更新线段树,直到要插入的位置的高度大于这次询问的高度H;最后处理区间查询,由于刚才已经把小于等于该次查询高度的位置都已经插入到了线段树中,所以询问的结果就是查询区间中被更新过的叶子节点的个数,也就是区间求和问题

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int MOD = 10000007; 
    const int maxn = 100000 + 5;
    const int N = 15;
    struct Node {        //每个节点的信息
        int h , pos;
        bool operator < (const Node tmp) const {
            return h < tmp.h;
        }
    } a[maxn];
    struct Section {    //每次查询的区间信息
        int L , R , H;
        int index;
        bool operator < (const Section tmp) const {
            return H < tmp.H;
        }
    } s[maxn];
    int cnt[maxn << 2] , ans[maxn];
    void PushUp(int rt)        
    {
        cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1];
    }
    void build()
    {
        memset(cnt , 0 , sizeof(cnt)); 
    }
    void update(int p , int l , int r , int rt)
    {
        if(l == r) {
            cnt[rt]++;
            return;
        }
        int m = (l + r) >> 1;
        if(p > m)        //找到更新点的位置
            update(p , rson);
        else
            update(p , lson);
        PushUp(rt);
    }
    int query(int L , int R , int l , int r , int rt)
    {
        if(L <= l && R >= r) {
            return cnt[rt];
        }
        int m = (l + r) >> 1;
        if(L > m)
            return query(L , R , rson);
        else if(R <= m)
            return query(L , R , lson);
        else
            return query(L , R , lson) + query(L , R , rson);
    }
    int main()
    {
        int T , i , j , n , m;
        cin >> T;
        for(int k = 1 ; k <= T ; k++)
        {
            build();
            printf("Case %d:
    " , k);
            scanf("%d %d" , &n , &m);
            for(i = 1 ; i <= n ; i++) {
                scanf("%d" , &a[i].h);
                a[i].pos = i;
            }
            for(i = 1 ; i <= m ; i++) {
                scanf("%d %d %d" , &s[i].L , &s[i].R , &s[i].H);
                s[i].index = i;
            }
            sort(a + 1 , a + n + 1);
            sort(s + 1 , s + m + 1);
            for(i = j = 1 ; i <= m ; i++) {        //这里就是上面的③
                while(a[j].h <= s[i].H && j <= n) {
                    update(a[j++].pos , 1 , n , 1);
                }
                ans[s[i].index] = query(s[i].L + 1 , s[i].R + 1 , 1 , n , 1);
            }
            for(i = 1 ; i <= m ; i++)
                printf("%d
    " , ans[i]);
        }
        return 0;
    }

      此题还可以用划分树来做,并且特别快,可惜我没学~

  • 相关阅读:
    conda更换为清华镜像源
    NVDIA的GPU驱动升级
    Windows使用nvidia-smi查看GPU信息
    查询GPU是否支持CUDA
    PyTorch教程【一】Pytorch环境的配置及安装
    JAVA基础篇—继承
    SQL
    随机数
    hdu 4751 Divide Groups 二分图
    hdu 4126 Genghis Khan the Conqueror hdu 4756 Install Air Conditioning 最小生成树
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4296171.html
Copyright © 2011-2022 走看看