HDU4417 Super Mario

划分树模板题

 1 #include<cstdio>
 2 #include<string>
 3 #include<vector>
 4 #include<algorithm>
 5 #define N 100009
 6 using namespace std;
 7 int n;
 8 int arr[N];//原数据
 9 int od[N];//排序后
10 int lfnum[20][N];//元素所在区间的当前位置进入左孩子的元素的个数
11 int val[20][N];//记录第k层当前位置的元素的值
12 bool cmp(const int &x,const int &y)
13 {
14     return arr[x]<arr[y];
15 }
16 void build(int l,int r,int d)
17 {
18     if(l==r) return;
19     int mid=(l+r)>>1,p=0;
20     for(int i=l; i<=r; i++)
21     {
22         if(val[d][i]<=mid)
23         {
24             val[d+1][l+p]=val[d][i];
25             lfnum[d][i]=++p;
26         }
27         else
28         {
29             lfnum[d][i]=p;
30             val[d+1][mid+i+1-l-p]=val[d][i];
31         }
32     }
33     build(l,mid,d+1);
34     build(mid+1,r,d+1);
35 }
36 //求区间[s,e]第k大的元素
37 int query(int s,int e,int k,int l=1,int r=n,int d=0)
38 {
39     if(l==r) return l;
40     int mid=(l+r)>>1,ss,ee;
41     ss=(s==l?0:lfnum[d][s-1]);
42     ee=lfnum[d][e];
43     if(ee-ss>=k) return query(l+ss,l+ee-1,k,l,mid,d+1);
44     return query(mid+1+(s-l-ss),mid+1+(e-l-ee),k-(ee-ss),mid+1,r,d+1);
45 }
46 int main()
47 {
48     int cas=0,m,l,r,T,ql,qr;
49     scanf("%d",&T);
50     while(T--)
51     {
52         printf("Case %d:\n",++cas);
53         scanf("%d%d",&n,&m);
54         for(int i=1; i<=n; i++) scanf("%d",arr+i),od[i]=i;
55         sort(od+1,od+n+1,cmp);
56         for(int i=1; i<=n; i++) val[0][od[i]]=i;
57         build(1,n,0);
58         while(m--)
59         {
60             int num,v;
61             scanf("%d%d%d",&ql,&qr,&v);
62             ql++;qr++;
63             l=1,r=qr-ql+1;
64             while(l<=r)
65             {
66                 int mid=(l+r)>>1;
67                 num=query(ql,qr,mid);
68                 if(arr[od[num]]>v) r=mid-1;
69                 else l=mid+1;
70             }
71             printf("%d\n",r);
72         }
73     }
74 }

 

posted @ 2012-09-24 11:06  qijinbiao1  阅读(249)  评论(0编辑  收藏  举报