UOJ Logo

NOI.AC

可能能获得图灵奖的伟大发明

2024-11-15 09:29:51 By one_zero_four_zero

以下代码通过使用二分等算法,可在 $O(nlog^2n)$ 的时间复杂度内

求出一个序列的最大值

代码如下

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define cur 300010
#define lowbit(x) ((x) & (-x))
using namespace std;

int N, ans = -1;
int A[300005];
int l = 0, r = 1000000000;
long long target;
int C[600055];

void update(int idx, int val){
    for (int i = idx; i <= cur + N; i += lowbit(i)){
        C[i] += val;
    }
}

int query(int idx){
    int res = 0;
    for (int i = idx; i; i -= lowbit(i)){
        res += C[i];
    }
    return res;
}

bool check(int x){
    memset(C, 0, sizeof(C));
    int nowval = 0;
    long long cnt = 0; // how much [i, j] med <= x
    for (int i = 1; i <= N; i ++){
        int tmp = (A[i] <= x) ? -1 : 1;
        update(cur + nowval, 1);
        nowval += tmp;
        cnt += i - query(cur + nowval - 1);
    }
    return cnt >= target;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("../data.in", "r", stdin);
    freopen("../data.out", "w", stdout);
#endif

    scanf("%d", &N);
    target = 1LL * (N + 1) * N / 2;
    for (int i = 1; i <= N; i ++){
        scanf("%d", &A[i]);
    }
    while (l <= r){
        int mid = (l + r) >> 1;
        if (check(mid)){
            ans = mid;
            r = mid - 1;
        }else{
            l = mid + 1;
        }
    }
    printf("%d\n", ans);

    return 0;
}

可以试试看

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。