题意:n个数 m个询问 ($n、m \le 10^5$)
每个询问有l, r, k 问的是[l, r]区间内有多少个数小于等于k
用主席树做的话查询第i小的数与k比较即可
1 #define lson l, m 2 #define rson m+1, r 3 const int N=1e5+5; 4 int L[N<<5], R[N<<5], sum[N<<5]; 5 int tot; 6 int a[N], T[N], Hash[N]; 7 int build(int l, int r) 8 { 9 int rt=(++tot); 10 sum[rt]=0; 11 if(l<r) 12 { 13 int m=(l+r)>>1; 14 L[rt]=build(lson); 15 R[rt]=build(rson); 16 } 17 return rt; 18 } 19 20 int update(int pre, int l, int r, int x) 21 { 22 int rt=(++tot); 23 L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+1; 24 if(l<r) 25 { 26 int m=(l+r)>>1; 27 if(x<=m) 28 L[rt]=update(L[pre], lson, x); 29 else 30 R[rt]=update(R[pre], rson, x); 31 } 32 return rt; 33 } 34 35 int query(int u, int v, int l, int r, int k) 36 { 37 if(l>=r) 38 return l; 39 int m=(l+r)>>1; 40 int num=sum[L[v]]-sum[L[u]]; 41 if(num>=k) 42 return query(L[u], L[v], lson, k); 43 else 44 return query(R[u], R[v], rson, k-num); 45 } 46 47 int main() 48 { 49 int t, ca=1; 50 scanf("%d", &t); 51 while(t--) 52 { 53 tot=0; 54 int n, m; 55 scanf("%d%d", &n, &m); 56 for(int i=1; i<=n; i++) 57 { 58 scanf("%d", &a[i]); 59 Hash[i]=a[i]; 60 } 61 sort(Hash+1, Hash+n+1); 62 int d=unique(Hash+1, Hash+n+1)-Hash-1; 63 T[0]=build(1, d); 64 for(int i=1; i<=n; i++) 65 { 66 int x=lower_bound(Hash+1, Hash+d+1, a[i])-Hash; 67 T[i]=update(T[i-1], 1, d, x); 68 } 69 printf("Case %d:\n", ca++); 70 while(m--) 71 { 72 int l, r, k; 73 scanf("%d%d%d", &l, &r, &k); 74 l++, r++; 75 int ll=1, rr=r-l+1; 76 int ans=0; 77 while(ll<=rr) 78 { 79 int mm=(ll+rr)>>1; 80 int tmp=Hash[query(T[l-1], T[r], 1, d, mm)]; 81 if(tmp<=k) 82 { 83 if(mm==r-l+1 || Hash[query(T[l-1], T[r], 1, d, mm+1)]>k) 84 { 85 ans=mm; 86 break; 87 } 88 ll=mm+1; 89 } 90 else 91 { 92 if(mm==1 || Hash[query(T[l-1], T[r], 1, d, mm-1)]<=k) 93 { 94 ans=mm-1; 95 break; 96 } 97 rr=mm-1; 98 } 99 } 100 printf("%d\n", ans); 101 } 102 } 103 return 0; 104 }
HDOJ 4417
时间: 2024-10-06 01:28:46