51nod 1682 中位数计数【想法题】

来源:互联网 发布:阿里云带宽收费标准 编辑:程序博客网 时间:2024/05/16 00:55

题目: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;}
0 0
原创粉丝点击