SPOJ 3267(DQUERY) D-query 【主席树】【离线树状数组】
来源:互联网 发布:涂色 app 源码 编辑:程序博客网 时间:2024/03/28 20:34
题目链接
persistent segment tree
题意
给一串数列,有q个(1e5的数量级)询问,求i到j间的不同数字的个数
分析
这个题有几种做法,可以用主席树、离线树状数组,还可以直接用莫队。这里写一下主席树和离线树状数组的做法
主席树做法
若用线段树,父子节点之间存的状态不好合并,这时先考虑一个简化的问题:对于一个序列,它的某个前缀有多少个不同的数?
此时,既然起始位置已经定了下来,那么对于序列中同样的一个数,必定只需要记录前面那个数就行了。这个问题就可以把所有数第一次出现的位置用线段树维护起来解决。
既然前缀如此,后缀也类似,只不过总是记录最晚出现的位置。而任意一个区间都可以看作以某个数为结尾的后缀,这时,我们只需要把原序列按每个数作为后缀的起点来建立n棵线段树,从而快速求得区间中不同数的个数。为了节约空间,自然要用主席树来解决。
离线树状数组做法
待更新……
AC代码
主席树
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cctype>#include <cstdlib>#include <cstring>#include <vector>#include <set>#include <string>#include <map>#include <queue>#include <deque>#include <list>#include <sstream>#include <stack>using namespace std;#define cls(x) memset(x,0,sizeof x)#define inf(x) memset(x,0x3f,sizeof x)#define neg(x) memset(x,-1,sizeof x)#define ninf(x) memset(x,0xc0,sizeof x)#define st0(x) memset(x,false,sizeof x)#define st1(x) memset(x,true,sizeof x)#define lowbit(x) x&(-x)#define input(x) scanf("%d",&(x))#define inputt(x,y) scanf("%d %d",&(x),&(y))#define bug cout<<"here"<<endl;//#pragma comment(linker, "/STACK:1024000000,1024000000")//stack expansion//#define debugconst double PI=acos(-1.0);const int INF=0x3f3f3f3f;//1061109567-2147483647const long long LINF=0x3f3f3f3f3f3f3f3f;//4557430888798830399-9223372036854775807const int maxn=300000+1000;int a[maxn];int n,q;/* 主席树 */struct chairNode{ int sum; int ls,rs;};struct chairmanTree{ chairNode tree[maxn*20]; int root[maxn]; size_t tsize; map<int,int> occur; int left,right; void Push_Up(int x) { tree[x].sum=tree[tree[x].ls].sum+tree[tree[x].rs].sum; return; } /* 建树 */ void build(int n,int L,int R) { left=L;right=R; cls(root); tsize=1; tree[0].ls=tree[0].rs=tree[0].sum=0;//零结点要指向自己 occur.clear(); for(int i=1;i<=n;++i) { if(occur.count(a[i])) root[i]=insert(insert(root[i-1],occur[a[i]],L,R,-1),i,L,R,1); else root[i]=insert(root[i-1],i,L,R,1); occur[a[i]]=i; } return; } /* 插入结点 */ int insert(int x,int pos,int L,int R,int v) { tree[tsize++]=tree[x]; x=tsize-1; if(L==R) { tree[x].sum+=v; return x; } int mid=(L+R)>>1; if(pos<=mid) tree[x].ls=insert(tree[x].ls,pos,L,mid,v); else tree[x].rs=insert(tree[x].rs,pos,mid+1,R,v); Push_Up(x); return x; } int answer(int start,int endd) { return query(root[endd],start,left,right); } int query(int x,int pos,int L,int R) { if(L==pos&&R==pos) return tree[x].sum; int mid=(L+R)>>1; if(pos<=mid) return query(tree[x].ls,pos,L,mid)+tree[tree[x].rs].sum; else return query(tree[x].rs,pos,mid+1,R); }}seq;int main(){ //ios::sync_with_stdio(false); //cin.tie(0); #ifdef debug freopen("E:\\Documents\\code\\input.txt","r",stdin); freopen("E:\\Documents\\code\\output.txt","w",stdout); #endif //IO while(input(n)!=EOF) { for(int i=1;i<=n;++i) input(a[i]); input(q); seq.build(n,1,n); int a,b; while(q--) { inputt(a,b); printf("%d\n",seq.answer(a,b)); } } return 0;}
树状数组离线
待更新……
0 0
- SPOJ 3267(DQUERY) D-query 【主席树】【离线树状数组】
- SPOJ DQUERY D-query 树状数组离线
- SPOJ 3267 DQUERY(主席树在线|树状数组离线)
- SPOJ D-query 树状数组离线&&主席树在线
- spoj DQUERY D-query SPOJ -(主席树)
- SPOJ DQUERY树状数组离线or主席树
- SPOJ DQUERY 离线树状数组or主席树
- SPOJ DQUERY D-query 主席树
- SPOJ 3267. D-query (主席树or树状数组离线)
- SPOJ D-query 区间不同数的个数 [在线主席树 or 离线树状数组]
- spoj D-query 区间不同数个数 主席树||离线+树状数组
- SPOJ DQUERY(树状数组离线处理 or 主席树 区间不同数个数)
- SPOJ DQUERY (离线数状数组||在线主席树)
- SPOJ DQUERY (离线数状数组||在线主席树)
- [SPOJ 3267] D-query (离线询问+树状数组)
- SPOJ DQUERY - D-query
- SPOJ - DQUERY 【主席树】
- spoj DQUERY - D-query(区间不同数的个数 主席树 or BIT)
- lambda表达式的使用
- openWRT 驱动开发举例
- String
- 第五章 数组Ivor Horton
- STM32学习---时钟系统
- SPOJ 3267(DQUERY) D-query 【主席树】【离线树状数组】
- 关于IDEA中部署网页时发生资源路径问题的解决方案
- 简单化的支付宝集成Demo
- qsort的用法
- 欢迎使用CSDN-markdown编辑器
- JS制作常见通知信息(适用于手机通知信息和电脑通知信息)
- 【Android】Suggestion: use tools:overrideLibrary="" to force usage
- Linux私房菜——第六章笔记
- Candies--差分约束系统