HDU 4417 主席树

来源:互联网 发布:小白素材vip源码 编辑:程序博客网 时间:2024/04/30 11:55
区间查询<=H的数有多少个

查询[l,r]区间只需要将第r棵线段树[0,H]区间的总数减去第l-1棵的就行了。

需要注意的是边界的处理

#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+6;struct node {int l,r,sum;}T[maxn*20];int root[maxn],a[maxn],cnt;vector <int> q;int getid(int x){return lower_bound(q.begin(),q.end(),x)-q.begin()+1;};void update(int l,int r,int x,int &y,int pos){    T[++cnt]=T[x];T[cnt].sum++;y=cnt;    if(l==r) return ;    int m = (l+r)>>1;    if(m>=pos) update(l,m,T[x].l,T[y].l,pos);    else update(m+1,r,T[x].r,T[y].r,pos);}int query(int l,int r,int x,int y,int pos){    if(l==r) return T[y].sum-T[x].sum;    int m = (l+r)>>1;    int ans = 0;    if(m>=pos)    {        ans += query(l,m,T[x].l,T[y].l,pos);    }    else    {        ans += T[T[y].l].sum-T[T[x].l].sum;        ans += query(m+1,r,T[x].r,T[y].r,pos);    }    return ans;}int main(){    int i,n,m,t,x,y,k,cas=1;    scanf("%d",&t);    while(t--)    {        cnt=0;q.clear();        scanf("%d%d",&n,&m);        for(i=1;i<=n;i++) scanf("%d",a+i),q.push_back(a[i]);        sort(q.begin(),q.end());q.erase(unique(q.begin(),q.end()),q.end());        for(i=1;i<=n;i++) update(1,n,root[i-1],root[i],getid(a[i]));        printf("Case %d:\n",cas++);        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&x,&y,&k);            int xx = getid(k);            if(q[xx-1]!=k) xx--;<span style="white-space:pre"></span>//边界处理 若k不在vector里,取<k的第一个数            if(!xx) printf("0\n");<span style="white-space:pre"></span>//若比最小的数还小,直接输出0            else printf("%d\n",query(1,n,root[x],root[y+1],xx));        }    }    return 0;}


0 0