码迷,mamicode.com
首页 > 其他好文 > 详细

【OJ1751】最佳南瓜

时间:2018-08-03 23:42:04      阅读:284      评论:0      收藏:0      [点我收藏+]

标签:while   node   str   operator   template   stdin   sqrt   include   题目   

1751 -- 最佳南瓜(Solution)

题目大意 : 给你一个长度为 \(N\) 的数列和 \(M\) 个操作,操作为将一段区间 \(+1\) 。要求每次操作后求出数列的中位数是多少 ( \(N,M\le10^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('\n');
    }
    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】最佳南瓜

标签:while   node   str   operator   template   stdin   sqrt   include   题目   

原文地址:https://www.cnblogs.com/farway17/p/9416878.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!