OJ1751最佳南瓜

Posted farway17

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OJ1751最佳南瓜相关的知识,希望对你有一定的参考价值。

1751 -- 最佳南瓜(Solution)

题目大意 : 给你一个长度为 (N) 的数列和 (M) 个操作,操作为将一段区间 (+1) 。要求每次操作后求出数列的中位数是多少 ( (N,Mle10^5+1) ,保证 (N) 为奇数)

Tag: 二分、分块

Analysis By LC:

这道题和2130是一个套路,都是转化为二分答案求解:求一个数满足不超过该数的数 (ge (N+1)/2) 个,求这样的数的最小值,该数即为中位数。那么仍然和2130一样维护每个块排序后的数列,利用STL的 (bound) 查询不超过某数的个数。与2130不同的是,这题不能每次询问后都二分答案,否则会超时。我们观察到由于每次操作为 (+1) ,所以中位数要么和上次一样要么 (+1) 。所以我们只需判断上次答案是否可行,不可行 (+1) 即可。

Code By LC :

#include<cstdio>
#include<algorithm>
using namespace std;
namespace io { //zzy的读入板子,orzzzy
    const int SIZE = (1 << 21) + 1;
    char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55]; int f,qr;
    #define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
    inline void flush () {
        fwrite (obuf, 1, oS - obuf, stdout);
        oS = obuf;
    }
    inline void putc (char x) {
        *oS ++ = x;
        if (oS == oT) flush ();
    }
    template <class I>
    inline void gi (I &x) {
        for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
        for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
    }
    template <class I>
    inline void print (I x) {
        if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
        while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
        while (qr) putc (qu[qr --]);
        putc('
');
    }
    struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::gi;
using io::print;
const int N=100005,INF=100100005;
int L,n,q,ind,l[N],r[N],id[N],ta[N],isl[N],pos[N];
struct node
{
    int id,w;
    bool operator < (const node x) const {
        return w < x.w;
    }
} s[N];
void rebuild(int x)
{
    sort(s+l[x],s+1+r[x]);
    for(int i=l[x];i<=r[x];i++)
        pos[s[i].id]=i;
}
bool check(int mid)
{
    int k=0;
    for(int i=1;i<=ind;i++)
    {
        int tmp=upper_bound(s+l[i],s+1+r[i],(node){-1,mid-ta[i]})-s;
        k+=tmp-l[i];
    }
    return k>=L;
}
int main()
{
    gi(n); gi(q); L=(n+1)/2;
    const int m=sqrt(n);
    for(int i=1;i<=n;i=min(n,i+m-1)+1)
    {
        l[++ind]=i,r[ind]=min(n,i+m-1);
        isl[i]=ind;
    }
    for(int i=1;i<=ind;i++)
        for(int j=l[i];j<=r[i];j++) id[j]=i;
    for(int i=1;i<=n;i++)
    {
        s[i].id=i;
        gi(s[i].w);
    }
    for(int i=1,k=0;i<=ind;i++) sort(s+l[i],s+1+r[i]);
    for(int i=1;i<=n;i++) pos[s[i].id]=i;
    int tl=1,tr=INF;
    while(tl<=tr)
    {
        int mid=tl+tr>>1;
        if(check(mid)) tr=mid-1;
        else tl=mid+1;
    } ++tr;
    while(q--)
    {
        int ql,qr,i;
        gi(ql); gi(qr);
        for(;ql<=qr&&!isl[ql];ql++) s[pos[ql]].w++;
        rebuild(id[ql-1]);
        if(ql<=qr)
        {
            for(i=isl[ql];i<=ind&&r[i]<=qr;i++)ta[i]++;
            if(i<=ind) for(ql=l[i];ql<=qr;ql++)s[pos[ql]].w++;
            rebuild(i);
        }
        if(!check(tr)) ++tr;
        print(tr);
    }
}

以上是关于OJ1751最佳南瓜的主要内容,如果未能解决你的问题,请参考以下文章

OJ2171最佳路径

ZSTU OJ 4272 最佳淘汰算法

POJ1751Highways

九度oj 题目1397:查找数段

更新片段参数的最佳实践?

POJ1751 Highways最小生成树