SPOJ3267--D-query(离线线段树||在线主席树)
来源:互联网 发布:求好听的淘宝店铺名字 编辑:程序博客网 时间:2024/05/16 11:49
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 subsequence ai, ai+1, ..., aj.
Input
- Line 1: n (1 ≤ n ≤ 30000).
- Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
- Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
- In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).
Output
- For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.
Example
Input51 1 2 1 331 52 43 5Output323
题意:求区间内元素的种数
思路:如果有一个询问u,v。则ans[v].push_back(u)。
然后就从左往右扫描,先更新数,如果没出现过很好处理。如果出现过,删除之前的出现记录,然后出现点更新为这个地方。然后如果这个点有 询问,就query一下。
线段树维护区间内的数种数。
#include <iostream>#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;#define maxn 30800#define maxm 1008000#define lson id<<1,l,mid#define rson id<<1|1,mid+1,rint pos[maxm],key[maxn],Ans[208000];struct ST{int l,r,sum;}st[maxn<<2];void PushUp(int id){st[id].sum = st[id<<1].sum + st[id<<1|1].sum;}void buildtree(int id,int l,int r){st[id].l = l,st[id].r = r;st[id].sum = 0;if(l == r)return;int mid = (l+r) >> 1;buildtree(lson);buildtree(rson);}void Update(int id,int p){if(st[id].l == p && st[id].r == p){st[id].sum ^= 1;return;}if(st[id<<1].r >= p)Update(id<<1,p);else Update(id<<1|1,p);PushUp(id);}int Query(int id,int l,int r){if(st[id].l == l && st[id].r == r)return st[id].sum;if(st[id<<1].r >= r)return Query(id<<1,l,r);else if(st[id<<1|1].l <= l)return Query(id<<1|1,l,r);return Query(id<<1,l,st[id<<1].r) + Query(id<<1|1,st[id<<1|1].l,r);}vector <int> ans[maxn];vector <int> num[maxn];int main(){//freopen("in.txt","r",stdin);int n;while(scanf("%d",&n)!=EOF){memset(pos,0,sizeof(pos));for(int i = 1;i <= n;i++)scanf("%d",&key[i]);for(int i = 1;i <= n;i++){num[i].clear();ans[i].clear();}int m;scanf("%d",&m);for(int i = 1;i <= m;i++){int u,v;scanf("%d%d",&u,&v);ans[v].push_back(u);num[v].push_back(i);}buildtree(1,1,n);for(int i = 1;i <= n;i++){if(pos[key[i]])Update(1,pos[key[i]]);Update(1,i);pos[key[i]] = i;for(int j = 0;j < ans[i].size();j++){int u = ans[i][j];Ans[num[i][j]] = Query(1,u,i);}}for(int i = 1;i <= m;i++)printf("%d\n",Ans[i]);}return 0;}
此题也可在线做,用主席树。
给数组的每一个后缀都建立一棵线段树,然后从后往前。类似于上面线段树的做法,线段树中一个数之前出现过,从左往右扫的过程中不断将这个数出现的位置往右更新。。而主席树我从右往左扫,不断将数出现的位置往左更新。
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define maxn 30080#define maxm 6008000int T[maxn],key[maxn];int Pos[1008000];int c[maxm],lson[maxm],rson[maxm];int tot,n;int build(int l,int r){int root = tot++;c[root] = 0;if(l != r){int mid = (l+r) >> 1;lson[root] = build(l,mid);rson[root] = build(mid+1,r);}return root;}int update(int root,int pos,int val){int newnode = tot++,tmp = newnode;c[newnode] = c[root] + val;int l = 1,r = n;while(l < r){int mid = (l+r) >> 1;if(pos <= mid){lson[newnode] = tot++;rson[newnode] = rson[root];newnode = lson[newnode];root = lson[root];r = mid;}else {rson[newnode] = tot++;lson[newnode] = lson[root];newnode = rson[newnode];root = rson[root];l = mid + 1;}c[newnode] = c[root] + val;}return tmp;}int query(int root,int pos){int ret = 0;int l = 1,r = n;while(pos < r){int mid = (l+r) >> 1;if(pos <= mid){r = mid;root = lson[root];}else {ret += c[lson[root]];root = rson[root];l = mid + 1;}}return ret + c[root];}int main(){//freopen("in.txt","r",stdin);while(scanf("%d",&n)!=EOF){memset(Pos,0,sizeof(Pos));tot = 0;for(int i = 1;i <= n;i++)scanf("%d",&key[i]);T[n+1] = build(1,n);for(int i = n;i;i--){if(Pos[key[i]])//如果这个数曾经出现过{int t = update(T[i+1],Pos[key[i]],-1);Pos[key[i]] = i;T[i] = update(t,i,1);}else {Pos[key[i]] = i;T[i] = update(T[i+1],i,1);}}int m;scanf("%d",&m);while(m--){int l,r;scanf("%d%d",&l,&r);printf("%d\n",query(T[l],r));}}return 0;}
0 0
- SPOJ3267--D-query(离线线段树||在线主席树)
- spoj3267 D-query 主席树(可持久化线段树)
- 【SPOJ3267】D-query-主席树应用
- SPOJ3267 D-Query 树状数组离线操作 或 主席树 查询某一区间内有多少不同的数
- SPOJ D-query 树状数组离线&&主席树在线
- SPOJ D-query 区间不同数的个数 [在线主席树 or 离线树状数组]
- 主席树|线段树(区间不同的数的个数)spoj3267
- SPOJ 3267(DQUERY) D-query 【主席树】【离线树状数组】
- ZOJ3633 Alice's present 线段树离线 || 主席树在线
- HDU 4417 线段树离线&&主席树在线
- SPOJ 3267. D-query (主席树or树状数组离线)
- spoj D-Query(主席树)
- spoj-D-query(主席树)
- spoj D-query 区间不同数个数 主席树||离线+树状数组
- SPOJ 3267 主席树||线段树+离线
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- 基于MTD的NAND驱动开发
- 可以说没有这句话,这些字就不会有这个群体的发生
- 【git】gitweb 404 错误
- MongDB学习笔记(二):索引操作
- Add new device
- SPOJ3267--D-query(离线线段树||在线主席树)
- 由" failed to run the android sdk manager"引起的一系列问题 android
- Oracle 配置FAST Cache最佳实践与限制
- 动态注册JNI
- java多线程 sleep()和wait()的区别
- MapReduce----主成分分析
- MFC网络编程,CSocket,网络通信,网络聊天室
- 移植测试工具到android
- 记录学习JavaWeb的点点滴滴(1)