UVALive 6860 Most Influential Pumpkin

来源:互联网 发布:js控制display显示 编辑:程序博客网 时间:2024/05/22 00:47

题意:给你一个序列,每次操作可以使一段连续的序列加1,每次更新完后输出这个序列的中位数。

注意到中位数的大小只会增加,不会减小,并且每次操作后最多使中位数加1.

将原序列分块操作,若块在询问的【L,R】中,则使块的cnt++,这样只对询问区间的首尾单独操作即可。

每次更新后查找序列中小于等于当前中位数的个数,如果个数小于等于n/2.则中位数++。

查找小于等于中位数的个数时用lower_bound会超时,可以存一个计数器p表示更新前的个数,因为大部分的区间p值不会改变。(但是最坏复杂度大了很多= =)


代码:

#include<bits/stdc++.h>#define fi first#define se second#define pb push_back#define lson o<<1#define rson o<<1|1#define CLR(A, X) memset(A, X, sizeof(A))using namespace std;typedef long long LL;typedef pair<int, int> PII;const double eps = 1e-10;int dcmp(double x){if(fabs(x)<eps) return 0; return x<0?-1:1;}const int N = 6e4+5;struct node {    int len, cnt, p;    PII a[300];    void clear() { len = cnt = p = 0; }    void push_back(int x, int y) { a[len++] = {x, y}; }    void my_sort() { sort(a, a+len); }    void update(int L, int R) {        for(int i = 0; i < len; i++) {            if(a[i].se<=R && a[i].se>=L) {                a[i].fi++;            }        }        my_sort();    }    int sum(int x) {        while(p>=0 && a[p].fi+cnt>x) p--;        while(p+1<len && a[p+1].fi+cnt<=x) p++;        return p+1;    }}b[300];int a[N];int main() {    int n, q, x;    while(~scanf("%d%d", &n, &q)) {        if(!n && !q) continue;        int len = sqrt(n+0.5), tot = n/len+!!(n%len);        for(int i = 0; i < tot; i++) b[i].clear();        for(int i = 0; i < n; i++) {            scanf("%d", &a[i]);            b[i/len].pb(a[i], i);        }        for(int i = 0; i < tot; i++) b[i].my_sort();        sort(a, a+n);        int Mid = a[n/2];        while(q--) {            int L, R;            scanf("%d%d", &L, &R);            L--, R--;            for(int i = L/len+1; i < R/len; i++) b[i].cnt++;            if(L/len == R/len) b[L/len].update(L, R);            else {                b[L/len].update(L, (L/len+1)*len-1);                b[R/len].update((R/len)*len, R);            }            int tmp = 0;            for(int i = 0; i < tot; i++) {                tmp += b[i].sum(Mid);            }            if(tmp <= n/2) Mid++;            printf("%d\n", Mid);        }    }    return 0;}