SPOJ - DQUERY(主席树)

2024-02-11 02:08
文章标签 主席 spoj dquery

本文主要是介绍SPOJ - DQUERY(主席树),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

题意:询问区间不同数字的个数。

思路:这题莫队,树状数组都可以写,主席树做法:我们需要维护每个数最后一次出现位置,所有最后一次出现位置对整个区间有1的贡献,也就是对每一个数建一棵线段树,如果这个数之前出现过则再建一棵树删除。

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll ;
const int maxn = 2e5+7;
const int mod = 1e9+7;
int n, m, cnt, root[maxn], a[maxn], pre[maxn], l, r, k, ans;
vector<int> v;
struct node{int l, r, sum;} T[maxn*25];
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}void update(int l,int r,int &now, int pre, int pos, int c)
{T[++cnt] = T[pre], T[cnt].sum += c, now = cnt;if(l == r) return;int mid = (l + r) >> 1;if(mid >= pos) update(l, mid, T[now].l, T[pre].l, pos, c);else update(mid + 1, r, T[now].r, T[pre].r, pos, c);
}
int query(int l, int r, int rt, int L, int R)
{if(L <= l && r <= R) return T[rt].sum;int mid = (l + r) / 2;int res = 0;if(mid >= L)  res += query(l, mid, T[rt].l, L, R);if(mid < R)  res += query(mid+1, r, T[rt].r, L, R);return res;
}
int main()
{scanf("%d",&n);for(int i = 1; i <= n; i++) scanf("%d",&a[i]),v.push_back(a[i]);sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());for(int i = 1; i <= n; i++){int pos = getid(a[i]);update(1, n, root[i], root[i-1], i, 1);if(pre[pos]) update(1, n, root[i], root[i], pre[pos], -1);pre[pos] = i;}scanf("%d", &m);for(int i = 1; i <= m; i++){scanf("%d%d", &l, &r);printf("%d\n", query(1, n, root[r], l, r));}return 0;
}
/*
5
1 1 2 1 3
3
1 5
2 4
3 5
*/

 

这篇关于SPOJ - DQUERY(主席树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/698573

相关文章

【POJ】2104 K-th Number 静态第K小——主席树

传送门:【POJ】2104 K-th Number 题目分析: 哇咔咔,又get了一个新技能——主席树,初步学习主席树,一次AC,感觉好棒~ 也在此Orz一下发明者主席——fotile96,在叉姐群经常看到主席的身影,不过蒟蒻也只能仰望神犇的背影了,起步迟且天赋不如人,只能慢慢的走下去,希望有一天能看到另一个世界。 主席树的编程方式是函数式编程(可持久化),保证我们可以查询历史

【SPOJ】1825 Free tour II 点分治

传送门:【SPOJ】1825 Free tour II 题目分析:敲了两遍。。。 本题是论文题,具体见漆子超论文《分治算法在树的路径问题中的应用》。 在以root为根的第 i 棵子树上,我们用G[ i ,j ]表示root的第 i 棵子树的路径上严格有 j 个黑点的路径的最长长度。用F[ i ,j ]表示在root为根的第 i 棵子树的路径上不超过 j 个黑点的路径的最长长度。因

【SPOJ】Triple Sums【FFT】

传送门:【SPOJ】Triple Sums 题目分析: 首先我们不考虑 i<j<k i<j<k这个条件,构造多项式: Y=∑xai \qquad\qquad\qquad Y = \sum x^{a_i} 那么 ai+aj+ak=S ai+aj+ak=S的个数即 xai+aj+ak=S x^{a_i+a_j+a_k=S}的个数,等价于 Y3中xS Y^3中x^S的系数。 然后我们考虑容斥

【SPOJ】【AGGRCOW】

总结:函数之间存在依赖。  然后一处修改了但是忘记修改另外的一处了。。。 #include <iostream>#include <cstring>#include <cmath>#include <queue>#include <stack>#include <list>#include <map>#include <set>#include <string>#inclu

SPOJ 1825 FTOUR2 - Free tour II (树上点分治)

题目地址:SPOJ 1825 树分治的题果然除了模板题就是金牌题啊。。。这题是一道论文题,想了好长时间。。。。终于过了,,,,注意一个坑点,如果权值全部为负的话,是可以不选任意一条边的,这样权值为0。。。也就是说初始值要设为0。。。 具体看漆子超的论文《分治算法在树的路径问题中的应用》。。 代码如下: #include <iostream>#include <string.h>#inc

SPOJ 1825 Free tour II

论文题: 在以root为根的第 i 棵子树上,我们用G[ i ,j ]表示root的第 i 棵子树的路径上严格有 j 个黑点的路径的最长长度。用F[ i ,j ]表示在root为根的第 i 棵子树的路径上不超过 j 个黑点的路径的最长长度。 因为所有子树里包含黑点数最多的路径的包含黑点数len可以O(N)求出,我们按照每棵子树的len从小到大的顺序遍历,这样就能将G和F数组降低一维,以G[ i

SPOJ - QTREE (树链剖分)

基础的树链剖分题目,不过是边权,可以向下映射成点权或者按边剖分。 VIEW CODE #include <iostream>#include<stdio.h>#include<cmath>#include<string.h>#include<algorithm>#include<string>using namespace std;const int mmax=100

spoj3267 D-query 主席树(可持久化线段树)

题目链接 题意:给n个数,m次查询,求[l,r]之间不重复数的个数。 思路:主席树。用一个map记录每个值在当前操作下最新的位置,从前往后插入主席树。对于查询[l,r],窝们在root[ l ]下查询在r之前的不重复数的个数。详见代码: /*********************************************************file name: spoj3267.

spoj 227

留着 #include <cstdio>#include <cstring>#include <cstdlib>#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1const int MAXN = 200010;int pos[MAXN];int sum[MAXN << 2];// = MAXN*4int ans[

spoj 416

又臭又长的烂代码 ...... #include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define maxn 1010using namespace std;char a[1010];int num[10],last;//bool cc(int sum)