SPOJ - DQUERY: D-query 离线处理 + 树状数组

题目链接:https://vjudge.net/problem/SPOJ-DQUERY

题意:给定数字序列,求任意区间内的不同数字的个数

解法:用树状数组维护 1 ~ i 的区间内不同数字个数的前缀和,首要解决的问题就是同一区间内相同数字统计时相互影响的问题,解决方法如下:离线存储查询的区间,对查询区间按照左端点排序,这样可以优先处理左边的           元素;然后预处理出每一元素下一跳到相同元素的 nxt[]; 这样随着坐标轴指针 l 的移动,l 左边的元素将不会产生任何影响,因为所产生的影响会在前缀和的做差运算中抵消;只需要对 l 指针左区间的元素的下一跳的位           置进行 add + 1 操作,从而更新当前查询区间的信息。

BIT代码实现:

 1 //190ms    19.5MB
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4
 5 const int N = 30010;
 6 const int M = 200010;
 7 int a[N], bit[N];
 8
 9 void init() {
10     memset(bit, 0, sizeof(bit));
11 }
12
13 int lowbit(int x) {
14     return x & -x;
15 }
16
17 void add(int x, int val) {
18     while(x < N) {
19         bit[x] += val;
20         x += lowbit(x);
21     }
22 }
23
24 int sum(int x) {
25     int ret = 0;
26     while(x > 0) {
27         ret += bit[x];
28         x -= lowbit(x);
29     }
30     return ret;
31 }
32
33 struct Query{
34     int l, r, p;
35     bool operator < (const Query& p)const{
36         return l < p.l;
37     }
38 } query[M];
39 int n, q;
40 map<int, int> mp;
41 int nxt[N], ans[M];
42
43 int main()
44 {
45     scanf("%d", &n);
46     mp.clear();
47     init();
48     for (int i = 1; i <= n; ++ i) {
49         scanf("%d", &a[i]);
50         if(mp.find(a[i]) == mp.end()) {
51             mp[a[i]] = i;
52             add(i, 1);
53         }
54     }
55     mp.clear();
56     for (int i = n; i >= 1; -- i) {
57         if(mp.find(a[i]) == mp.end()) nxt[i] = n + 1;
58         else nxt[i] = mp[a[i]];
59         mp[a[i]] = i;
60     }
61     scanf("%d", &q);
62     for (int i = 1; i <= q; ++ i) {
63         scanf("%d%d", &query[i].l, &query[i].r);
64         query[i].p = i;
65     }
66     sort(query+1, query+1+q);
67     int pp = 1;
68     for (int i = 1; i <= q; ++ i) {
69         while(pp<=n && pp < query[i].l) add(nxt[pp++], 1);
70         ans[query[i].p] = sum(query[i].r) - sum(query[i].l-1);
71     }
72     for (int i = 1; i <= q; ++ i) printf("%d\n", ans[i]);
73     return 0;
74 }

时间: 2024-10-03 14:06:11

SPOJ - DQUERY: D-query 离线处理 + 树状数组的相关文章

HDU 3333 Turing Tree (离散化+离线处理+树状数组)

Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick t

【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改

题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i个元素的值.接下来q行,每行包含两个整数l和r,代表一次询问. 输出 对于每次询问,输出一行,代表询问的答案. 样例输入 5 5 5 2 4 1 3 1 5 1 3 2 4 3 5 2 5 样例输出 28 17 11 11 17 题解 单调栈+离线+扫描线+树状数组区间修改 首先把使用单调栈找出每个

CF 351D, 离线处理+树状数组/莫队算法

颓颓颓 题目大意:给你m个区间询问,询问区间内有多少个不相同的数以及存不存在一种数字组成的数列为等差间隔的数列. 解:离线询问,不相同的数其实是老做法了,但是巧妙的是数字是否为等差间隔.我们把询问按右区间排序,可知等差间隔必然是连续的一段,那么从当前枚举点往左,合法数列必然是连续的一段,那么我们用树状数组+1-1维护区间延伸到哪里,然后询问[l,i]当中和是否为零就知道有没有符合的连续一段等差间隔数列了. 顺便这题官解是莫队,正好我也去研究一下莫队吧,现在先贴一个离线nlogn的做法,递归学会莫

codeforces 703D Mishka and Interesting sum 偶数亦或 离线+前缀树状数组

题目传送门 题目大意:给出n个数字,m次区间询问,每一次区间询问都是询问 l 到 r 之间出现次数为偶数的数 的亦或和. 思路:偶数个相同数字亦或得到0,奇数个亦或得到本身,那么如果把一段区间暴力亦或,得到的其实就是出现次数为奇数的数字的亦或和,所以我们希望这段区间内的所有数字出现次数都+1,使奇偶性互换. 我们先处理出前缀的亦或和,这样可以得到次数为奇数的亦或和. 接下来的问题就是要改变一段区间的奇偶性了,也就是说,这个问题其实就转化成了如何求一段区间出现的所有数字(无重复). 这里我学到的是

CCPC河南省赛B-树上逆序对| 离线处理|树状数组 + 线段树维护逆序对 + dfs序 + 离散化

B题地址:树上逆序对 有两个思路 方法一:线段树离线 + 树状数组或者线段树维护区间和 0:离散化,离线存储输入的operation操作序列. ①:先线段树在dfs序上离线处理好整一棵树:在dfs序上先查询"加入当前结点的逆序对权值和"并记录,再加入当前这个节点:dfs完毕后,就已经记录好每个结点的dfs序出入时间戳(转化成区间问题了)和每个 ②:使用树状数组或者新的线段树在dfs序上插入逆序对权值 为什么能这样呢?因为dfs序维护了每个结点遍历的顺序,每个结点的dfs序时间戳肯定比它

hdu-3333 Turing Tree 离线区间+树状数组(区间不同数的和)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 题目大意: 给出一数组,以及m个查询区间,每次查询该区间不同数字的和.相同数字只加一次. 解题思路: 离线区间,按照区间右端点进行排序. 这样可以从左到右扫一遍,用尺取法一个一个将数字放入树状数组中. 如果这个数字已经在树状数组里面,记录之前的下标,再从树状数组中删去之前下标的这个数字,在当前下标添加该数字.这样可以保证每一步操作,都会使得树状数组中没有重复元素.这样可以直接用树状数组求不同

Leetcode——2 Range Sum Query - Mutable(树状数组实现)

Problem: Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. The update(i, val) function modifies nums by updating the element at index i to val. Example: Given nums = [1, 3, 5] sumRange(0, 2) -> 9 up

Codeforces Gym 100114 H. Milestones 离线树状数组

H. Milestones Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description The longest road of the Fairy Kingdom has n milestones. A long-established tradition defines a specific color for milestones in each region, with a

sdut2610---Boring Counting(离线+树状数组+离散化)

Boring Counting Time Limit: 3000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence. Now you task is to answer a list of queries, for each query,