[主席树]HDOJ4417 Super Mario

题意: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

 

posted @ 2015-07-20 21:11  Empress  阅读(249)  评论(0编辑  收藏  举报