zoukankan      html  css  js  c++  java
  • (树状数组+离线查询)HDU 4417

    题意:

    给定一个数列,最多10万次查询l到r不超过h的数字的个数。

    分析:

    唉,太菜啦。

    在线做法应该比较明显,区间维护平衡树,用线段树套平衡树,或者分块套平衡树,应该都能A,但是没试过,只是BB,如有错误欢迎指正。

    其实最方便的做法离线做法,太巧妙啦。

    把数列按升序排列,把所有查询按h升序排列。

    每次查询把比h的小的位置标记为1,查询用bit的sum(r)-sum(l-1)即可

    因为都是单调的,所以很方便。

    其实很多没有修改的区间问题都可以转化成离线问题。

    甚至于一些带修改的题都可以离线。

    这些题关键在于如何转化,也关键在于做题者的脑洞。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <vector>
     6 
     7 
     8 using namespace std;
     9 
    10 const int inf = 0x3f3f3f3f;
    11 const int maxn = 100010;
    12 
    13 int bit[maxn];
    14 int t, n, q;
    15 
    16 int sum(int i) {
    17     int s = 0;
    18     while(i > 0) {
    19         s += bit[i];
    20         i -= i & -i;
    21     }
    22     return s;
    23 }
    24 
    25 void add(int i, int x) {
    26     while(i <= n) {
    27         bit[i] += x;
    28         i += i & -i;
    29     }
    30 }
    31 
    32 struct Q {
    33     int l, r, h;
    34     int index;
    35 } query[maxn];
    36 
    37 bool cmp(Q a, Q b) {
    38     return a.h < b.h;
    39 }
    40 
    41 pair<int, int> a[maxn];
    42 int ans[maxn];
    43 
    44 int main() {
    45     scanf("%d", &t);
    46     int kase = 0;
    47     while(t--) {
    48         memset(bit, 0, sizeof(bit));
    49         scanf("%d%d", &n, &q);
    50         for(int i = 1; i <= n; i++) {
    51             scanf("%d", &a[i].first);
    52             a[i].second = i;
    53         }
    54         for(int i = 0; i < q; i++) {
    55             scanf("%d%d%d", &query[i].l, &query[i].r, &query[i].h);
    56             query[i].l++, query[i].r++;
    57             query[i].index = i;
    58         }
    59         sort(query, query + q, cmp);
    60         sort(a + 1, a + n + 1);
    61         int left = 1;
    62         for(int i = 0; i < q; i++) {
    63             while(left <= n && a[left].first <= query[i].h) {
    64                 add(a[left].second, 1);
    65                 left++;
    66             }
    67             int r = sum(query[i].r);
    68             int l = sum(query[i].l - 1);
    69             ans[query[i].index] = r - l;
    70         }
    71         printf("Case %d:
    ", ++kase);
    72         for(int i = 0; i < q; i++) {
    73             printf("%d
    ", ans[i]);
    74         }
    75     }
    76 
    77 
    78 
    79     return 0;
    80 
    81 }
  • 相关阅读:
    招聘里常见的沟通能力到底是什么
    C++服务器linux开发环境管理
    网络游戏通信协议双向迭代加密
    win10控制台程序printf死锁问题
    手游系统逻辑档案之通信协议
    STL插入删除和查询测试
    MATLAB复制图片时边框大的问题
    2019网易笔试题C++--丰收
    暴力求解最长公共子串
    顺时针打印矩阵
  • 原文地址:https://www.cnblogs.com/tak-fate/p/6882782.html
Copyright © 2011-2022 走看看