spoj 3267 D-query

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

------------------------------------------------------------------------------

主席树模板题之一 求不带修改的区间不同数个数

最近学习了下发现主席树就是可持久化线段树 由于每次单点修改只会改变一条链上的信息

所以我们可以把其余部分的信息重复利用 然后再新建一条链作为这次修改后的这条链的新状态

所以每次单点修改的时间复杂度和空间复杂度都是$O(logN)$

懂了原理后就像普通线段树一样按照自己的习惯来写就好 不需要准备什么模板

而对于这种求区间不同的数的个数的问题 我们只需维护对于每种前缀区间 每个数最后一次出现位置

然后所有最后一次出现位置对整个区间有$1$的贡献

这样就可以根据询问的区间右端点对应的版本 用区间减法来求区间不同数的个数

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 3e4 + 10, T = N * 50, L = 1e6 + 10;
 4 int sum[T], ch[T][2], root[N << 1], ma[N], last[L];
 5 int croot, cnt, n, q;
 6 void build(int x, int L, int R)
 7 {
 8     if(L == R)
 9     {
10         sum[x] = 0;
11         return;
12     }
13     int mid = (L + R) >> 1;
14     ch[x][0] = ++cnt;
15     build(cnt, L, mid);
16     ch[x][1] = ++cnt;
17     build(cnt, mid + 1, R);
18     sum[x] = sum[ch[x][0]] + sum[ch[x][1]];
19 }
20 void update(int x, int L, int R, int y, int delta, int pre)
21 {
22     if(L == R)
23     {
24         sum[x] = sum[pre] + delta;
25         return;
26     }
27     int mid = (L + R) >> 1;
28     if(y <= mid)
29     {
30         ch[x][0] = ++cnt;
31         update(cnt, L, mid, y, delta, ch[pre][0]);
32         ch[x][1] = ch[pre][1];
33     }
34     else
35     {
36         ch[x][0] = ch[pre][0];
37         ch[x][1] = ++cnt;
38         update(cnt, mid + 1, R, y, delta, ch[pre][1]);
39     }
40     sum[x] = sum[ch[x][0]] + sum[ch[x][1]];
41 }
42 int query(int x, int L, int R, int r)
43 {
44     if(R <= r)
45         return sum[x];
46     int mid = (L + R) >> 1;
47     if(r <= mid)
48         return query(ch[x][0], L, mid, r);
49     return
50         sum[ch[x][0]] + query(ch[x][1], mid + 1, R, r);
51 }
52 int main()
53 {
54     scanf("%d", &n);
55     root[++croot] = ++cnt;
56     ma[0] = 1;
57     build(cnt, 1, n);
58     int x, y;
59     for(int i = 1; i <= n; ++i)
60     {
61         scanf("%d", &x);
62         root[++croot] = ++cnt;
63         update(cnt, 1, n, i, 1, root[croot - 1]);
64         if(last[x])
65         {
66             root[++croot] = ++cnt;
67             update(cnt, 1, n, last[x], -1, root[croot - 1]);
68         }
69         last[x] = i;
70         ma[i] = root[croot];
71     }
72     scanf("%d", &q);
73     while(q--)
74     {
75         scanf("%d%d", &x, &y);
76         if(x > 1)
77             printf("%d\n", sum[ma[y]] - query(ma[y], 1, n, x - 1));
78         else
79             printf("%d\n", sum[ma[y]]);
80     }
81     return 0;
82 }
时间: 2024-11-10 01:19:00

spoj 3267 D-query的相关文章

SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)

DQUERY - D-query #sorting #tree English Vietnamese Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the

SPOJ - QTREE 375 Query on a tree 树链剖分+线段树

操作1:修改第k条边权. 操作2:询问两点间最大边权. 树链剖分,然后线段树维护最大值 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #inclu

SPOJ 3267. D-query (主席树or树状数组离线)

A - D-query Time Limit:1500MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice SPOJ DQUERY Appoint description:  System Crawler  (2014-12-06) Description English Vietnamese Given a sequence of n numbers a1, a2, ..., an and

SPOJ QTREE 375. Query on a tree

SPOJ Problem Set (classical) 375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHA

SPOJ 375 QTREE - Query on a tree(树链剖分)

题目链接:http://www.spoj.com/problems/QTREE/en/ 题意:  一棵树 n 个节点,每条边上有权值,同时有两个操作: (1)更改操作:CHANGE i ti(把第 i 条边上的权值改为 ti). (2)查询操作:QUERY a b(查询 a 到 b 的路径上权值最大的边的权值). 思路(树链剖分): 看到这种区间查询的题想要用数据结构优化,提高时间效率一般会想到线段树.可是这次操作的对象并不是一组序列, 无法直接使用线段树.这时,我们可以做些转化:对树作树链剖分

SPOJ 3267. D-query (主席树)

A - D-query Time Limit:1500MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the nu

spoj 375 QTREE - Query on a tree 树链剖分

题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set&g

【树链剖分模板】【SPOJ 375】 Query on a tree

375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

SPOJ 题目913QTREE2 - Query on a tree II(Link Cut Tree 查询路径第k个点)

QTREE2 - Query on a tree II no tags You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some i