HDU 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): 1254 Accepted Submission(s): 614
Total Submission(s): 1254 Accepted Submission(s): 614
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.
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
Recommend
We have carefully selected several similar problems for you: 4255 4247 4252 4246 4248
然後直接套求求區間第k小的模板就可以啦!
題目意思:
給出一組數,求給定區間內的中位數。解題思路:
中位數k=(r-l)/2+1;//l和r是給定查詢區間的兩個端點。然後直接套求求區間第k小的模板就可以啦!
#include <iostream>
#include <stdio.h>
#include <algorithm>
const int maxn = 100005;
using namespace std;
int sor[maxn];//藉助sort排序的陣列
struct node
{
int num[maxn];//當前層的數
int cnt[maxn]; //核心部分,儲存每一個元素的左邊的元素中位於下一層左子樹的個數
} tree[40];//40是樹的層數
//建樹程式碼如下
void buildtree(int l, int r, int d)//d是深度
{
if (l == r) return; //遞迴出口
int mid = (l+r)>>1;//劃分左右區間
int opleft = l, opright = mid+1;//對左右子樹的操作位置的初始化
int same_as_mid = 0;//和sor[mid]相同的數的數目
//計算在mid左邊有多少個和sor[mid]相同的數(包括mid),都要放到左子樹
for (int i = mid; i > 0; i--)
{
if (sor[i] == sor[mid]) same_as_mid++;
else break;
}
int cnt_left = 0;//被劃分到左子樹的個數
for (int i = l; i <= r; i++)
{
//從l到r開始遍歷
if (tree[d].num[i] < sor[mid])//左
{
tree[d+1].num[opleft++] = tree[d].num[i];
cnt_left++;
tree[d].cnt[i] = cnt_left;
}
else if(tree[d].num[i] == sor[mid] && same_as_mid)
{
//相同的都放在左子樹
tree[d+1].num[opleft++] = tree[d].num[i];
cnt_left++;
tree[d].cnt[i] = cnt_left;
same_as_mid--;
}
else//右
{
tree[d].cnt[i] = cnt_left;
tree[d+1].num[opright++] = tree[d].num[i];
}
}
buildtree(l, mid, d+1); //遞迴建樹
buildtree(mid+1, r, d+1);
}
int query(int l, int r, int d, int ql, int qr, int k) //在d層[l,r]的節點裡查詢[a,b]中的第k小值
{
if (l == r) return tree[d].num[l]; //遞迴出口
int mid = (l+r)>>1;
int sum_in_left;//區間內元素位於下一層左子樹的個數
int left;//[l,ql-1]左邊的元素中位於下一層左子樹的個數
if (ql == l)
{
//如果ql是節點的左邊界則有cnt[qr]個數進入左子樹
sum_in_left = tree[d].cnt[qr];
left = 0;
}
else
{
//如果ql不是節點的左邊界則有cnt[qr]-cnt[ql-1]個數進入了左子樹
sum_in_left = tree[d].cnt[qr] - tree[d].cnt[ql-1];
left = tree[d].cnt[ql-1];
}
if (sum_in_left >= k)
{
//要找的點在左子樹
//確定下一步詢問的位置:
//如果在ql的左邊有left個進入左子樹
//那麼ql到qr中第一個進入左子樹的必定在l+left的位置
int new_ql = l+left;
int new_qr = new_ql+sum_in_left-1;
return query(l, mid, d+1, new_ql, new_qr, k);
}
else//要找的點在右子樹
{
//確定下一步詢問的位置
int a = ql - l - left;//表示當前區間左半部分即[l,ql-1]中在下一層是右孩子的個數
int b = qr - ql + 1 - sum_in_left;//表示當前區間右半部分即[ql,qr]中在下一層是右孩子的個數
int new_ql = mid + a + 1;
int new_qr = mid + a + b;
//k-sum_in_left表示要減去區間裡已經進入左子樹的個數
return query(mid+1, r, d+1, new_ql, new_qr, k - sum_in_left);
}
}
int main()
{
int n,m,i,a,b,k,cnt=0;
while(~scanf("%d",&n))
{
printf("Case %d:\n",++cnt);
for(i=1; i<=n; ++i)
{
scanf("%d",&sor[i]);//先插入到sor陣列
tree[0].num[i]=sor[i];//再插入第一層
}
sort(sor+1,sor+n+1);//升序排列
buildtree(1,n,0);//建樹
scanf("%d",&m);
for(i=1; i<=m; ++i)
{
//查詢
scanf("%d%d",&a,&b);
k=(b-a)/2+1;//k是區間ab的中位數
printf("%d\n",query(1,n,0,a,b,k));
}
}
return 0;
}
相關文章
- hud--4251The Famous ICPC Team Again+劃分樹入門題AI
- HDU 4417-Super Mario(劃分樹-二分查詢)
- HDU 1754 I Hate It (線段樹 區間最值)
- HDU 1698 Just a Hook (線段樹區間更新)Hook
- hdu4417 樹狀陣列(求指定區間比指定數小的數的個數)陣列
- 763. 劃分字母區間
- HDU1698 Just a Hook【線段樹基礎:區間修改+區間查詢】Hook
- POJ 3468 【區間修改+區間查詢 樹狀陣列 | 線段樹 | 分塊】陣列
- 區間眾數(分塊)
- HDU 1848 Fibonacci again and again(SG函式)AI函式
- HDU 1556【區間更新+單點查詢 樹狀陣列】陣列
- poj 3237 樹鏈剖分(區間更新,區間查詢)
- HYSBZ 2243 樹鏈剖分(區間更新,區間查詢)較難
- HDU - 1702 - ACboy needs your help again!AI
- HDU 4252A Famous City(弱資料可以使用貪心)
- HDU1754 I Hate It 【線段樹基礎:點修改+區間查詢】
- HDU 1848 Fibonacci again and again (尼姆博弈+sg函式)AI函式
- D 區間求和 [數學 樹狀陣列]陣列
- 線段樹維護區間等差數列
- hdu 2665 可持久化線段樹求區間第K大值(函式式線段樹||主席樹)持久化函式
- HDU 1556-Color the ball(樹狀陣列-區間修改 單點查詢)陣列
- 求區間不同數的個數【樹狀陣列求解】陣列
- (hdu 1698) Just a Hook(區間更新)Hook
- [資料結構] 劃分樹資料結構
- Java中的記憶體區域劃分Java記憶體
- mysql 求分組中位數、環比、同比、中位數的環比、同比MySql
- 【樹狀陣列 單點修改,區間求值】hdu 1166 敵兵佈陣陣列
- JVM區域劃分JVM
- hdu 1789 Doing Homework again(簡單貪心)AI
- hdu5435 數位dp(大數的處理)
- 演算法:區間樹演算法
- 01 分數規劃
- 01分數規劃
- 分塊=-=優雅的暴力=-=中位數模版
- 區間動態規劃動態規劃
- HDU 6034 Balala Power!(大數進位制)
- leetcode刷題.763. 劃分字母區間.每日打卡LeetCode
- ACM The Famous ClockACM