标签:while node str operator template stdin sqrt include 题目
题目大意 : 给你一个长度为 \(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);
}
}
标签:while node str operator template stdin sqrt include 题目
原文地址:https://www.cnblogs.com/farway17/p/9416878.html