题目:www.51nod.com/onlineJudge/questionCode.html#!problemId=1682
题意:
中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均数作为中位数。
现在有n个数,每个数都是独一无二的,求出每个数在多少个包含其的区间中是中位数。
Input
第一行一个数n(n<=8000)
第二行n个数,0<=每个数<=10^9
Output
N个数,依次表示第i个数在多少包含其的区间中是中位数。
Input示例
5
1 2 3 4 5
Output示例
1 2 3 2 1
分析:
这题看错n的范围了,以为是6000(因为刚做了一个6000的题)….T_T…..
然后想也没想就以为是主席树模板题了,枚举每个区间,然后主席树找这个区间中位数。结果T了,时间复杂度是O(n^2logn),难道卡常数?
然后看了讨论,囧,原来看错数据范围了~~
正解是枚举每个数作为中位数x,那么这比这个数大的和比这个数小的数的数目是一样的。所以找这个中位数x所在的区间,那么对于这个数左边,统计>x和
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5;
int a[N], num[N], ans[N];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) {
int cnt = 0;
memset(num, 0, sizeof(num));
for (int j = i; j >= 1; j--) {
if (a[j] > a[i]) ++cnt;
if (a[j] < a[i]) --cnt;
num[8000 + cnt]++;
}
cnt = 0;
for (int j = i; j <= n; j++) {
if (a[j] > a[i]) --cnt;
if (a[j] < a[i]) ++cnt;
ans[i] += num[8000 + cnt];
}
}
for (int i = 1; i <= n; i++)
printf("%d%c", ans[i], i == n ? '\n' : ' ');
return 0;
}
T的代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e4;
struct Node {
int L, R, sum;
};
Node T[MAXN * 20];
int T_cnt;
void insert(int &num, int &x, int L, int R) {
T[T_cnt++] = T[x];
x = T_cnt - 1;
++T[x].sum;
if(L == R) return ;
int mid = (L + R) >> 1;
if(num <= mid) insert(num, T[x].L, L, mid);
else insert(num, T[x].R, mid + 1, R);
}
int query(int i, int j, int k, int L, int R) {
if(L == R) return L;
int t = T[T[j].L].sum - T[T[i].L].sum;
int mid = (R + L) >> 1;
if(k <= t) return query(T[i].L, T[j].L, k, L, mid);
else return query(T[i].R, T[j].R, k - t, mid + 1, R);
}
struct A {
int x, idx;
bool operator < (const A &rhs) const {
return x < rhs.x;
}
};
A a[MAXN];
int rk[MAXN], root[MAXN],num[MAXN];
int n, m;
int main() {
T[0].L = T[0].R = T[0].sum = 0;
root[0] = 0;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i].x);
a[i].idx = i;
}
sort(a + 1, a + n + 1);
for(int i = 1; i <= n; ++i) rk[a[i].idx] = i;
T_cnt = 1;
for(int i = 1; i <= n; ++i) {
root[i] = root[i - 1];
insert(rk[i], root[i], 1, n);
}
for(int i=1; i<=n; i++) {
num[a[i].idx]++;
for(int j=i+1; j<=n; j++) {
if((j-i+1)&1)
num[a[query(root[i - 1], root[j], (j-i)/2+1, 1, n)].idx]++;
}
}
for(int i=1; i<=n; i++)
printf("%d ",num[i]);
return 0;
}