bzoj 1112: [POI2008]砖块Klo【对顶堆】

priority_queue实现的对顶堆,细节超级多WA了十几次……但是理论上是最简便的orz其实是我已经不会写平衡树了
枚举左端点,显然要把这一段的高度搞成(l,l+k-1)的高度中位数,所以需要一个支持插入删除查询中位数的东西,我们使用对顶堆
然后关于删除,我们手动维护size和sum,删的时候直接减掉就行,然后堆里面放二元组高度和i,需要使用堆顶的时候,把i<l的pop掉就是可用堆顶了
注意q1最大值<=q2最小值,虽然判了但是还是会WA,在调整size的时候顺便判一下即可

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=100005;
int n,m,a[N],bl[N];
long long sm1,sm2,si1,si2,mn,ansl,ansm;
struct qwe
{
    int v,id;
    qwe(int V=0,int ID=0)
    {
        v=V,id=ID;
    }
    bool operator < (const qwe &b) const
    {
        return v<b.v;
    }
};
struct ewq
{
    int v,id;
    ewq(int V=0,int ID=0)
    {
        v=V,id=ID;
    }
    bool operator < (const ewq &b) const
    {
        return v>b.v;
    }
};
priority_queue<qwe>q1;
priority_queue<ewq>q2;
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>'9'||p<'0')
    {
        if(p=='-')
            f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9')
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
void del(int i)
{
    while(!q1.empty()&&q1.top().id<i)
        q1.pop();
    while(!q2.empty()&&q2.top().id<i)
        q2.pop();
}
void tiao(int i)
{
    del(i);
    while(!q1.empty()&&!q2.empty()&&q1.top().v>q2.top().v)
    {
        del(i);
        si1--,si2++;
        sm1-=q1.top().v,sm2+=q1.top().v;
        q2.push(ewq(q1.top().v,q1.top().id)),q1.pop();
    }
    while(si1<si2)
    {
        del(i);
        si1++,si2--;
        sm1+=q2.top().v,sm2-=q2.top().v;
		bl[q2.top().id]=1;
        q1.push(qwe(q2.top().v,q2.top().id)),q2.pop();
    }
    while(si1-1>si2)
    {
        del(i);
        si1--,si2++;
        sm1-=q1.top().v,sm2+=q1.top().v;
		bl[q1.top().id]=2;
        q2.push(ewq(q1.top().v,q1.top().id)),q1.pop();
    }
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=1;i<=m;i++)
        q1.push(qwe(a[i],i)),sm1+=a[i],si1++,bl[i]=1;
    tiao(1);
    ansl=1,ansm=q1.top().v,mn=ansm*si1-sm1+sm2-ansm*si2;//cerr<<endl;
    //cerr<<q1.top().id<<" "<<q1.top().v<<"   "<<sm1<<" "<<sm2<<"   "<<si1<<" "<<si2<<endl;
    for(int i=2;i+m-1<=n;i++)
    {
        if(bl[i-1]==1)
            sm1-=a[i-1],si1--;
        else
            sm2-=a[i-1],si2--;
        tiao(i);
        del(i);
        if(a[i+m-1]<=q1.top().v)
            q1.push(qwe(a[i+m-1],i+m-1)),sm1+=a[i+m-1],si1++,bl[i+m-1]=1;
        else
            q2.push(ewq(a[i+m-1],i+m-1)),sm2+=a[i+m-1],si2++,bl[i+m-1]=2;
        tiao(i);
        del(i);
        // cerr<<q1.top().id<<" "<<q1.top().v<<"   "<<sm1<<" "<<sm2<<"   "<<si1<<" "<<si2<<endl;
        if(q1.top().v*si1-sm1+sm2-q1.top().v*si2<mn)
            ansl=i,ansm=q1.top().v,mn=ansm*si1-sm1+sm2-ansm*si2;
    }
    printf("%lld\n",mn);
    // for(int i=1;i<=n;i++)
    // {
        // if(i>=ansl&&i<=ansl+m-1)
            // printf("%lld\n",ansm);
        // else
            // printf("%d\n",a[i]);
    // }
    return 0;
}
posted @ 2018-09-18 15:23  lokiii  阅读(199)  评论(0编辑  收藏  举报