hdoj 4251 The Famous ICPC Team Again

The Famous ICPC Team Again

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 203    Accepted Submission(s): 91


Problem Description
When Mr. B, Mr. G and Mr. M were preparing for the 2012 ACM-ICPC World Final Contest, Mr. B had collected a large set of contest problems for their daily training. When they decided to take training, Mr. B would choose one of them from the problem set. All the problems in the problem set had been sorted by their time of publish. Each time Prof. S, their coach, would tell them to choose one problem published within a particular time interval. That is to say, if problems had been sorted in a line, each time they would choose one of them from a specified segment of the line.

Moreover, when collecting the problems, Mr. B had also known an estimation of each problem’s difficultness. When he was asked to choose a problem, if he chose the easiest one, Mr. G would complain that “Hey, what a trivial problem!”; if he chose the hardest one, Mr. M would grumble that it took too much time to finish it. To address this dilemma, Mr. B decided to take the one with the medium difficulty. Therefore, he needed a way to know the median number in the given interval of the sequence.
 
Input
For each test case, the first line contains a single integer n (1 <= n <= 100,000) indicating the total number of problems. The second line contains n integers xi (0 <= xi <= 1,000,000,000), separated by single space, denoting the difficultness of each problem, already sorted by publish time. The next line contains a single integer m (1 <= m <= 100,000), specifying number of queries. Then m lines follow, each line contains a pair of integers, A and B (1 <= A <= B <= n), denoting that Mr. B needed to choose a problem between positions A and B (inclusively, positions are counted from 1). It is guaranteed that the number of items between A and B is odd.
 
Output
For each query, output a single line containing an integer that denotes the difficultness of the problem that Mr. B should choose.
 
Sample Input
5 5 3 2 4 1 3 1 3 2 4 3 5 5 10 6 4 8 2 3 1 3 2 4 3 5
 
Sample Output
Case 1: 3 3 2 Case 2: 6 6 4
 
Source
 
 
这题是直接划分树套模板 但是我没学过划分树 听他们说了我也不知道 百度搜到一篇关于POJ 询问第K个大的数 最典型的划分树的题目
以后遇到也是贴模板吧  确实不想去学了 懒啊!!!
这是运行最快的一个代码
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<stdio.h>
 4 using namespace std;
 5 const int A=100010;
 6 int srt[A];//排序数组
 7 int val[18][A];//记录每次划分时的元素
 8 int toleft[18][A];//toleft[i][j]第i层的第j个之前包括第j个有多少个被分到左孩子。
 9 struct Node{
10     int l,r;
11 };
12 inline int L(int x){ return (x<<1)+1;}
13 inline int R(int x){ return (x<<1)+2;}
14 Node node[A<<2];
15 
16 void build_tree(int s,int e,int row,int pos)
17 {
18     node[pos].l=s;
19     node[pos].r=e;
20     if(s==e) return;
21 
22     int mid=(s+e)>>1;
23     int lsame=mid+1-s;//lsame表示和srt[mid]相等且分到左边的元素的个数
24     for(int i=s;i<=e;i++)
25     {
26         if(val[row][i]<srt[mid])
27             lsame--;
28     }
29     int l=s;int r=mid+1;
30     for(int i=s;i<=e;i++) //计算被划分到左子树的元素个数。
31     {
32         toleft[row][i]=(i==s?0:toleft[row][i-1]);
33         if(val[row][i]<srt[mid])
34         {
35             val[row+1][l++]=val[row][i];
36             toleft[row][i]++;
37         }
38         else if(val[row][i]>srt[mid])
39         {
40             val[row+1][r++]=val[row][i];
41         }
42         else if(lsame)
43         {
44             val[row+1][l++]=val[row][i];
45             toleft[row][i]++;
46             lsame--;
47 
48         }
49         else
50         {
51             val[row+1][r++]=val[row][i];
52         }
53     }
54     build_tree(s,mid,row+1,L(pos));
55     build_tree(mid+1,e,row+1,R(pos));
56 
57 }
58 int query(int s,int e,int k,int row,int pos)
59 {
60     if(s==e) return val[row][s];
61     int LL= ((s==node[pos].l)?0:toleft[row][s-1]);//LL表示[ node[id].l , l-1 ]有多少个分到左边
62     int LI=toleft[row][e]-LL;//LI表示[ l , r ]有多少个分到左边
63     if(k<=LI)
64         return query(node[pos].l+LL,node[pos].l+LL+LI-1,k,row+1,L(pos));
65     int mid=(node[pos].l+node[pos].r)>>1;
66     int RL= s-node[pos].l-LL;//RL表示[ node[id].l , l-1 ]有多少个分到右边
67     int RI= e-s+1-LI; //RI表示[ l , r ]有多少个分到右边
68     return query(mid+1+RL,mid+1+RL+RI-1,k-LI,row+1,R(pos));
69 }
70 int main()
71 {
72     //freopen("1.txt","r",stdin);
73     //freopen("2.txt","w",stdout);
74     int m,n;
75     int sum=1;
76     while(~scanf("%d",&n))
77     {
78         printf("Case %d:\n",sum++);
79         for(int i=0;i<n;i++)
80         {
81             scanf("%d",srt+i);
82             val[0][i]=srt[i];
83         }
84         sort(srt,srt+n);
85         build_tree(0,n-1,0,0);
86         scanf("%d",&m);
87         int s,e,k;
88         for(int i=0;i<m;i++)
89         {
90             scanf("%d%d",&s,&e);
91             printf("%d\n",query(s-1,e-1,(e-s)/2+1,0,0));
92         }
93 
94     }
95 }
这是标程 但是运行了9S
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define ran 100010
 5 using namespace std;
 6 int n,m,a[ran],b[ran];
 7 int s[ran*18];
 8 void build(int i,int st,int en){
 9     memcpy(s+i+st,a+st,sizeof(int)*(en-st));
10     sort(s+i+st,s+i+en);
11     if(st+1==en)return;
12     int mi=(st+en)/2;
13     build(i+n,st,mi);
14     build(i+n,mi,en);
15 }
16 int calc(int i,int st,int en,int le,int ri,int x){
17     if(st==le && en==ri)
18         return lower_bound(s+i+st,s+i+en,x)-(s+i+st);
19     int mi=(st+en)/2;
20     if(ri<=mi)
21         return calc(i+n,st,mi,le,ri,x);
22     if(le>=mi)
23         return calc(i+n,mi,en,le,ri,x);
24     return calc(i+n,st,mi,le,mi,x)+calc(i+n,mi,en,mi,ri,x);
25 }
26 int main(){
27     int w,x,y;
28     for(int t=1; ~scanf("%d",&n); t++){
29         for(int i=0; i<n; i++){
30             scanf("%d",&a[i]);
31             b[i]=a[i];
32         }
33         sort(b,b+n);
34         m=unique(b,b+n)-b;
35         for(int i=0; i<n; i++)
36             a[i]=lower_bound(b,b+m,a[i])-b;
37         build(0,0,n);
38         printf("Case %d:\n",t);
39         for(scanf("%d",&w); w--;){
40             scanf("%d%d",&x,&y);--x;
41             int lo=0,hi=m-1;
42             while(lo!=hi){
43                 int mi=(lo+hi+1)/2;
44                 if(calc(0,0,n,x,y,mi)<=(y-x)/2)
45                     lo=mi;
46                 else
47                     hi=mi-1;
48             }
49             printf("%d\n",b[lo]);
50         }
51     }
52     return 0;
53 }
运行2S 短小精悍的代码
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<map>
 4 #include<vector>
 5 
 6 using namespace std;
 7 
 8 int n, m;
 9 int a[100005], x[100005];
10 vector<int> bit[100005];
11 
12 void add(int id, int v) {
13     while(v <= n) {
14         bit[v].push_back(id);
15         v += (v & -v);
16     }
17 }
18 
19 int query(int L, int R, int v) {
20     int u = 0, now = 0;
21     for(int i=20; i>=0; i--) {
22         if(u + (1<<i) <= n) {
23             u += (1<<i);
24             int g = upper_bound(bit[u].begin(), bit[u].end(), R) - lower_bound(bit[u].begin(), bit[u].end(), L);
25             if(now + g >= v) u -= (1<<i);
26             else now += g;
27         }
28     }
29     return x[u+1];
30 }
31 
32 int main() {
33     int test = 0;
34     while(scanf("%d", &n) != EOF) {
35         for(int i=1; i<=n; i++) {
36             scanf("%d", &a[i]);
37             x[i] = a[i];
38             bit[i].clear();
39         }
40         sort(x+1, x+n+1);
41         for(int i=1; i<=n; i++) {
42             a[i] = lower_bound(x+1, x+n+1, a[i]) - x;
43             add(i, a[i]);
44         }
45         for(int i=1; i<=n; i++) {
46             sort(bit[i].begin(), bit[i].end());
47         }
48         printf("Case %d:\n", ++test);
49         scanf("%d", &m);
50         for(int i=1, A, B; i<=m; i++) {
51             scanf("%d%d", &A, &B);
52             printf("%d\n", query(A, B, (B-A)/2+1));
53         }
54     }
55     return 0;
56 }


 

原文地址:https://www.cnblogs.com/wujianwei/p/2598621.html