码迷,mamicode.com
首页 > 编程语言 > 详细

(树状数组+离线查询)HDU 4417 - Super Mario

时间:2017-05-20 18:55:27      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:转化   memset   cstring   区间   nbsp   数字   oid   namespace   应该   

题意:

给定一个数列,最多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:\n", ++kase);
72         for(int i = 0; i < q; i++) {
73             printf("%d\n", ans[i]);
74         }
75     }
76 
77 
78 
79     return 0;
80 
81 }

 

(树状数组+离线查询)HDU 4417 - Super Mario

标签:转化   memset   cstring   区间   nbsp   数字   oid   namespace   应该   

原文地址:http://www.cnblogs.com/tak-fate/p/6882782.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!