SPOJ D-query 区间不同数的个数 [在线主席树 or 离线树状数组]
2016-03-03 09:56
761 查看
题意:给出N个数,M个询问,每次询问给出区间内不同数的个数。
解法:很经典的题目,可以将每一个数依次插入主席树,插入时,将这个位置+1,并将最近的一个等值的位置-1即可。然后对于询问区间L,R,只要在第R颗树上询问区间L,R的和就是答案。类似于这个思想,可以考虑离线处理询问,从左往右遍历插入,处理所有以这当前点为右端点的询问,这样就不需要可持久化了,并且树状数组就可以轻松维护了。
主席树代码:
解法:很经典的题目,可以将每一个数依次插入主席树,插入时,将这个位置+1,并将最近的一个等值的位置-1即可。然后对于询问区间L,R,只要在第R颗树上询问区间L,R的和就是答案。类似于这个思想,可以考虑离线处理询问,从左往右遍历插入,处理所有以这当前点为右端点的询问,这样就不需要可持久化了,并且树状数组就可以轻松维护了。
主席树代码:
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<iostream> #include<stdlib.h> #include<set> #include<map> #include<queue> #include<vector> #include<bitset> #pragma comment(linker, "/STACK:1024000000,1024000000") template <class T> bool scanff(T &ret){ //Faster Input char c; int sgn; T bit=0.1; if(c=getchar(),c==EOF) return 0; while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); if(c==' '||c=='\n'){ ret*=sgn; return 1; } while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10; ret*=sgn; return 1; } #define inf 1073741823 #define llinf 4611686018427387903LL #define PI acos(-1.0) #define lth (th<<1) #define rth (th<<1|1) #define rep(i,a,b) for(int i=int(a);i<=int(b);i++) #define drep(i,a,b) for(int i=int(a);i>=int(b);i--) #define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next) #define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++) #define mem(x,val) memset(x,val,sizeof(x)) #define mkp(a,b) make_pair(a,b) #define findx(x) lower_bound(b+1,b+1+bn,x)-b #define pb(x) push_back(x) using namespace std; typedef long long ll; typedef pair<int,int> pii; #define lowbit(x) (x&(-x)) #define N 230030 #define M 5005000 int tot,c[M],lson[M],rson[M]; int t ,n,qn,a ,b ,bn; int nxt ; int build(int l,int r){ int x=++tot; c[x]=0; if(l!=r){ int m=(l+r)>>1; lson[x]=build(l,m); rson[x]=build(m+1,r); } return x; } void update(int l,int r,int pos,int pre,int cur,int val){ lson[cur]=lson[pre]; rson[cur]=rson[pre]; c[cur]=c[pre]+val; if(l==r)return; int m=(l+r)>>1; if(pos<=m)update(l,m,pos,lson[pre],lson[cur]=++tot,val); else update(m+1,r,pos,rson[pre],rson[cur]=++tot,val); } int query(int th,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return c; int sum=0; int m=(l+r)>>1; if(m>=ql)sum+=query(lson ,l,m,ql,qr); if(m<qr)sum+=query(rson ,m+1,r,ql,qr); return sum; } int main(){ scanff(n); t[n+1]=build(1,n); rep(i,1,n)scanff(a[i]),b[++bn]=a[i]; sort(b+1,b+1+bn); bn=unique(b+1,b+1+bn)-b-1; rep(i,1,n)a[i]=findx(a[i]); rep(i,1,bn)nxt[i]=-1; drep(i,n,1){ t[i]=++tot; if(nxt[a[i]]==-1){ update(1,n,i,t[i+1],t[i],1); } else{ update(1,n,nxt[a[i]],t[i+1],t[i],-1); int temp=++tot; update(1,n,i,t[i],tot,1); t[i]=temp; } nxt[a[i]]=i; } scanff(qn); rep(i,1,qn){ int l,r; scanff(l);scanff(r); printf("%d\n",query(t[l],1,n,l,r)); } return 0; }
离线树状数组代码:#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<iostream> #include<stdlib.h> #include<set> #include<map> #include<queue> #include<vector> #include<bitset> #pragma comment(linker, "/STACK:1024000000,1024000000") template <class T> bool scanff(T &ret){ //Faster Input char c; int sgn; T bit=0.1; if(c=getchar(),c==EOF) return 0; while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); if(c==' '||c=='\n'){ ret*=sgn; return 1; } while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10; ret*=sgn; return 1; } #define inf 1073741823 #define llinf 4611686018427387903LL #define PI acos(-1.0) #define lth (th<<1) #define rth (th<<1|1) #define rep(i,a,b) for(int i=int(a);i<=int(b);i++) #define drep(i,a,b) for(int i=int(a);i>=int(b);i--) #define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next) #define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++) #define mem(x,val) memset(x,val,sizeof(x)) #define mkp(a,b) make_pair(a,b) #define findx(x) lower_bound(b+1,b+1+bn,x)-b #define pb(x) push_back(x) using namespace std; typedef long long ll; typedef pair<int,int> pii; #define lowbit(x) (x&(-x)) #define N 30030 #define M 200200 int n,qn; int nxt ; int a ,b ,c ,bn; struct query{ int l,r,idx; bool operator < (const query temp)const{ return r<temp.r; } }q[M]; int ans[M]; int add(int x,int val){ for(int i=x;i<=n;i+=lowbit(i)) c[i]+=val; } int getsum(int l,int r){ int suml=0,sumr=0; for(int i=l-1;i;i-=lowbit(i))suml+=c[i]; for(int i=r;i;i-=lowbit(i))sumr+=c[i]; return sumr-suml; } int main(){ scanff(n); rep(i,1,n)scanff(a[i]),b[++bn]=a[i]; sort(b+1,b+1+bn); bn=unique(b+1,b+1+bn)-b-1; rep(i,1,n)a[i]=findx(a[i]); scanff(qn); rep(i,1,qn){ scanff(q[i].l); scanff(q[i].r); q[i].idx=i; } sort(q+1,q+1+qn); int j=1; rep(i,1,n){ if(nxt[a[i]])add(nxt[a[i]],-1); add(i,1); while(q[j].r==i&&j<=qn){ ans[q[j].idx]=getsum(q[j].l,q[j].r); j++; } nxt[a[i]]=i; } rep(i,1,qn)printf("%d\n",ans[i]); return 0; }相关文章推荐
- question_012-JAVA之泛型通配符
- iOS状态栏UIStatusBar详解
- iOS7的适配小问题, uiscrollview中view向下偏移64
- HDU 2817 A sequence of numbers(快速幂)
- hdu---3177 Crixalis's Equipment 根据 两个元素 之间的权衡进行排序
- Build Active Architecture Only
- Break和Continue的一些注意事项
- NSAttributedString UIKit Additions 文章翻译参考
- =Cursor cursor = dbInstance.query(String table,String []Columns, String selection, String[]selectionArgs, String having, string orderBy);参数的意思
- SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model size阅读笔记
- GCD与NSOperationQueue的区别
- UI进阶之--网易彩票手写plist文件,动态创建控制器与tableViewcell
- 【ios】UIColor,CGColor,CIColor三者的区别和联系
- 334. Increasing Triplet Subsequence
- NSOperationQueue与GCD的使用原则和场景
- question_011-JAVA之Collection
- [LeetCode] Closest Binary Search Tree Value 最近的二分搜索树的值
- HTML中让表单input等文本框为只读不可编辑但可以获取value值的方法;让文本域前面的内容显示在左上角,居中
- Android UI学习 - FrameLayou和布局优化
- 详解 CALayer 和 UIView 的区别和联系