HDU - 4417 Super Mario 主席樹
阿新 • • 發佈:2018-06-20
數量 \n make In printf ons bound update ket
題意:
給一個數列$\{ a_i \}$,一些詢問$(l_i,r_i,h_i)$,求$j\in [l_i,r_i] ,a_j<=h_i$的元素數量
題解:
問區間內$<=h$的個數 等於是詢問$[l,r]$區間內$[0,upperbound(h)]$的元素個數,就可以
對於整個區間,很明顯是類似權值線段樹的逆序對問題,而對於$[l,r]$,利用主席樹的可減性進行求解即可
#include <bits/stdc++.h> #define nd seg[now] #define ndp seg[pre] #define mid ((s+t)>>1) using namespace std; const int maxn=1e5+10; int casn,n,m,k; int num[maxn],rt[maxn],size,pos[maxn]; struct node{ int l,r,sum; }seg[maxn*20]; void maketree(int s=1,int t=n,int &now=rt[0]){ now=++size;nd={s,t,0}; if(s==t) return ; maketree(s,mid,nd.l);maketree(mid+1,t,nd.r); } void update(int &now,int pre,int k,int s=1,int t=n){ now=++size;nd=ndp,nd.sum++; if(s==t) return ; if(k<=mid)update(nd.l,ndp.l,k,s,mid); else update(nd.r,ndp.r,k,mid+1,t); } int query(int now,int pre,int l,int r,int s=1,int t=n){ if(l>t||r<s||l>r) return 0; if(l<=s&&r>=t) return ndp.sum-nd.sum; return query(nd.l,ndp.l,l,r,s,mid)+query(nd.r,ndp.r,l,r,mid+1,t); } int main(){ scanf("%d",&casn); int tt=0; while(casn--){ scanf("%d%d",&k,&m); size=0; for(int i=1;i<=k;i++){ scanf("%d",num+i); pos[i]=num[i]; } sort(pos+1,pos+1+k); n=unique(pos+1,pos+1+k)-pos; maketree(); for(int i=1;i<=k;i++){ int id=lower_bound(pos+1,pos+1+n,num[i])-pos; update(rt[i],rt[i-1],id); } printf("Case %d:\n",++tt); while(m--){ int a,b,c; scanf("%d%d%d",&a,&b,&c); a++,b++; int k=upper_bound(pos+1,pos+1+n,c)-pos; if(pos[k]>c)k--; printf("%d\n",query(rt[a-1],rt[b],0,k)); } } return 0; }
HDU - 4417 Super Mario 主席樹