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
- 劃分樹模板+模板題--hdu4251
- hdu--4417Super Mario+劃分樹
- HDU 1848 Fibonacci again and again(SG函式)AI函式
- HDU-4348 - To the moon (主席樹+區間修改)
- HDU 2795 Billboard(線段樹 區間最大)
- HDU 3397 Sequence operation(線段樹區間染色加區間合併)
- HDU 1754 I Hate It (線段樹 區間最值)
- HDU 1848 Fibonacci again and again (尼姆博弈+sg函式)AI函式
- HDU1698 Just a Hook【線段樹基礎:區間修改+區間查詢】Hook
- 763. 劃分字母區間
- HDU 1556【區間更新+單點查詢 樹狀陣列】陣列
- HDU 4027 Can you answer these queries? (線段樹 區間開方)
- 劃分樹
- POJ 3468 【區間修改+區間查詢 樹狀陣列 | 線段樹 | 分塊】陣列
- 力扣:763.劃分字母區間力扣
- 區間眾數(分塊)
- HDU1754 I Hate It 【線段樹基礎:點修改+區間查詢】
- 求區間不同數的個數【主席樹求解】
- HDU - 6291 對稱數 (樹上莫隊+分塊) (2018CCPC女生賽)
- 線段樹維護區間等差數列
- HDU1166 敵兵佈陣【線段樹基礎:點修改+區間查詢】
- HDU1166 敵兵佈陣【樹狀陣列 單點修改+區間查詢】陣列
- HDU 6034 Balala Power!(大數進位制)
- leetcode刷題.763. 劃分字母區間.每日打卡LeetCode
- 求區間不同數的個數【樹狀陣列求解】陣列
- [資料結構] 劃分樹資料結構
- mysql 求分組中位數、環比、同比、中位數的環比、同比MySql
- 區間動態規劃動態規劃
- HDU 6274 Master of Sequence(思維+樹狀陣列+二分)AST陣列
- 01 分數規劃
- 01分數規劃
- 樹狀陣列的區間查詢與區間修改陣列
- 芻議線段樹 2 (區間修改,區間查詢)
- 2020 ICPC 上海賽區
- 線段樹 transformation——hdu 4578ORM
- [動態規劃] 區間 dp動態規劃
- 分塊=-=優雅的暴力=-=中位數模版
- 區間更新+差分