标签:memory sorted win get question file got first number
Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 59481 | Accepted: 20727 | |
Case Time Limit: 2000MS |
Description
Input
Output
Sample Input
7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3
Sample Output
5 6 3
Hint
Source
主席树(函数式线段树)裸题
主席树是一种离线数据结构,是由很多棵线段树组成的。
第i棵树代表第i个数出现前的情况
每个线段存数字的出现次数
听起来
肯定会MLE !
但是我们发现i和i-1的某些节点完全相同 所以只需要借用以前的点就可以 ,不需要新建。
那么如果要询问i-j之间数字出现的次数怎么办呢?
因为每一棵线段树的区间都是相同的,所以要求l-r之间的数字的出现次数只要用前r位出现的次数减去前l-1位出现的次数,就是ans
但是如果有修改操作怎么办?
如果沿用上面的做法,那么修改操作是O(nlogn)的,查询是O(1)的,修改要花好长时间。。。
前缀和联想到了树状数组,那么将前缀和用树状数组维护的话修改是O(logn*logn),查询时O(logn),查询的时间虽然变长,但是修改的时间缩短许多!!
注意:
函数式线段树的数组要开大一点!!
转载自http://blog.csdn.net/regina8023/article/details/41910615
现在还不会主席树,先敲下模板,以后会用到的
本题没涉及到修改
#include <algorithm> #include <cstdio> #define N 105000 using std::sort; using std::unique; using std::lower_bound; struct cmt { int l,r,Size; }tr[N*20]; int a[N],b[N],t[N],tot,Size,n,m,T; int build(int l,int r) { int root=++tot; tr[root].Size=0; if(l==r) return root; int mid=(l+r)>>1; tr[root].l=build(l,mid); tr[root].r=build(mid+1,r); return root; } int update(int rt,int x) { int now=++tot; int tmp=now; tr[now].Size=tr[rt].Size+1; for(int mid,l=1,r=Size;l<=r;) { mid=(l+r)>>1; if(x<=mid) { tr[now].l=++tot; tr[now].r=tr[rt].r; rt=tr[rt].l; now=tot; r=mid-1; } else { tr[now].l=tr[rt].l; tr[now].r=++tot; rt=tr[rt].r; now=tot; l=mid+1; } tr[now].Size=tr[rt].Size+1; } return tmp; } int ask(int lx,int rx,int k) { int l=1,r=Size; for(int mid;l<=r;) { mid=(l+r)>>1; if(tr[tr[rx].l].Size-tr[tr[lx].l].Size>=k) { rx=tr[rx].l; lx=tr[lx].l; r=mid-1; } else { k-=tr[tr[rx].l].Size-tr[tr[lx].l].Size; rx=tr[rx].r; lx=tr[lx].r; l=mid+1; } } return l; } int main() { scanf("%d",&T); for(;T--;) { tot=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+1+n); Size=unique(b+1,b+1+n)-b-1; t[0]=build(1,Size); for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+Size,a[i])-b; for(int i=1;i<=n;++i) t[i]=update(t[i-1],a[i]); for(int x,y,k;m--;) { scanf("%d%d%d",&x,&y,&k); printf("%d\n",b[ask(t[x-1],t[y],k)]); } } return 0; }
标签:memory sorted win get question file got first number
原文地址:http://www.cnblogs.com/ruojisun/p/7404393.html