12
22
2015
0

【JSOI2015】最佳南瓜

易知,每次操作后中位数要么不变要么增加一。因此我们只要分块判断此时的中位数是否需要加一。

代码:

 

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,mid,x,y,L,R,len,num,sum,k;
int l[10010],r[10010],b[100010],tag[10010];
struct node{int x,id;}a[100010];
bool cmp(const node x,const node y){return x.x<y.x;}
void add(int x,int L,int R)
{
    for (int i=l[x];i<=r[x];i++)if (a[i].id>=L&&a[i].id<=R)a[i].x++;
    sort(a+l[x],a+r[x]+1,cmp);
}
int binary(int l,int r,int x)
{
    if (l==r) return l;
    int mid=(l+r)>>1;
    if (a[mid].x>=x) return binary(l,mid,x);return binary(mid+1,r,x);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].x);
        a[i].id=i;
    }
    for (int i=1;i<=n;i++)
        b[i]=a[i].x;
    nth_element(b+1,b+(n/2)+1,b+n+1);
    mid=b[n/2+1];
    len=(int)sqrt(n);
    if (n%len) num=n/len+1;else num=n/len;
    for (int i=1;i<=num;i++)
    {
        l[i]=(i-1)*len+1;
        r[i]=min(n,i*len);
        sort(a+l[i],a+r[i]+1,cmp);
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        L=x/len;
        if (x>r[L]) L++;
        R=y/len;
        if (y>r[R]) R++;
        if (L==R) add(L,x,y);else
        {   
            add(L,x,r[L]);add(R,l[R],y);
            for (int j=L+1;j<R;j++) tag[j]++;
        }
        sum=0;
        mid++;
        for (int j=1;j<=num;j++)
        {
            k=binary(l[j],r[j],mid-tag[j]);
            if (a[k].x>=mid-tag[j]) k--;
            if (k>=l[j]) sum+=k-l[j]+1;
        }
        if (sum>n/2) mid--;
        printf("%d\n",mid);
    }
}
Category: 分块 | Tags: | Read Count: 362

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com