Problem 2288 谁还不是个宝宝
Accept: 4 Submit: 9
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
洪尼玛有n个朋友,n个朋友排成一排,每个朋友都有一个自身的价值Ai,并且每个朋友自身的价值均不相同。现在每个朋友都能与他左右的若干个人组成一个区间,也可以他自己一个人组成一个区间。若这个区间的人数为奇数个,那么我们称其为“可行区间”。将一个 “可行区间”里所有朋友按价值排序后,中间的那个朋友就是这个“可行区间”里的“宝宝”。求每个朋友是多少个“可行区间”里的“宝宝”?
Input
多组测试数据。
输入第一行为正整数n,表示朋友个数。
接下来一行,有n个互不相同的正整数Ai,表示第i个朋友的价值。
n≤1000,Ai≤10^9
Output
输出n个正整数,依次表示第i个朋友是多少个“可行区间”里的“宝宝”。
Sample Input
5 1 2 3 4 5
Sample Output
1 2 3 2 1
Hint
例如3能组成的“可行间”有:{3},{1,2,3},{2,3,4},{3,4,5},{1,2,3,4,5} 共5个区间,其中在{3},{2,3,4},{1,2,3,4,5} 这3个“可行区间”里是宝宝。
Source
福州大学第十五届程序设计竞赛_重现赛
【题目链接】http://acm.fzu.edu.cn/problem.php?pid=2288
【思路】用两个优先队列维护大顶堆和小顶堆,小顶堆中放比a[mid]小的元素,大顶堆中放比a[mid]大的元素,每次通过比较两个队列的大小来求解mid元素。每次先把mid和a[mid] push进size比较大的一个队列中去,然后通过pop 和 push操作使得当前两个队列的size相差为1,最后size较大的队列的队首元素就是新的mid。
【时间复杂度】n*(logn)^2
【代码如下】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int a[2100],n,cnt[2100];
struct node{
int indx,num;
node(int x, int y):indx(x),num(y){}
friend bool operator<(node A, node B){ //大顶堆
return A.num < B.num;
}
};
struct Node{
int indx,num;
Node(int x, int y):indx(x),num(y){}
friend bool operator<(Node A, Node B){ //小顶堆
return A.num > B.num;
}
};
int main(){
while(~scanf("%d",&n)){
for(int i = 1; i <= n; i ++) scanf("%d",&a[i]);
memset(cnt,0,sizeof(cnt));//cnt[i]统计下标为i的元素符合条件的答案
for(int i = 1; i <= n; i ++){
priority_queue<node>pqa;//大顶堆维护队列
priority_queue<Node>pqb;//小顶堆维护队列
int mid=-1,siza=0,sizb=0;
for(int j = i; j <= n; j += 2){
if(mid==-1) {mid=j;cnt[mid]++; continue;}
else{
int l=j-1,r=j;
if(a[l]<a[mid]) pqa.push(node(l,a[l])),siza++;
else pqb.push(Node(l,a[l])),sizb++;
if(a[r]<a[mid]) pqa.push(node(r,a[r])),siza++;
else pqb.push(Node(r,a[r])),sizb++;
}
if(siza==sizb) cnt[mid]++;
else{
int flag=0;
if(siza>sizb) pqa.push(node(mid,a[mid])),siza++,flag=1;
while(siza-1>sizb){
node no = pqa.top(); pqb.push(Node(no.indx,no.num));
pqa.pop();
siza--; sizb++;
}
if(siza<sizb) pqb.push(Node(mid,a[mid])),sizb++,flag=2;
while(siza<sizb-1){
Node no=pqb.top(); pqa.push(node(no.indx,no.num));
pqb.pop();
siza++; sizb--;
}
if(flag==1){
node no = pqa.top(); mid = no.indx; pqa.pop(); siza--;
}
else if(flag==2){
Node no = pqb.top(); mid = no.indx; pqb.pop(); sizb--;
}
cnt[mid] ++;
}
}
}
for(int i = 1; i <= n; i ++){
if(i>1) printf(" ");
printf("%d",cnt[i]);
}
printf("\n");
}
return 0;
}