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最佳南瓜的主要内容,如果未能解决你的问题,请参考以下文章