P3466 [POI2008]KLO-Building blocks

Posted lovedsr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3466 [POI2008]KLO-Building blocks相关的知识,希望对你有一定的参考价值。

目录

题目

luogu
csdn好像限制了展开博客次数,真的好xx偶

思路

显然一段区间内的值一定是他的中位数
少一点比多一点好
然后就可以枚举区间了
区间答案为
val[mid]-小于val[mid]的+大于val[mid]-val[mid]的所有值
就是size[x]val[mid] - tot_l + tot_r - size[y]val[mid]
然后你随便写个treap(fhq)就好了

错误

一开始siz[x]直接写成mid
但这是错误的,因为如果有多个数字都等于中位数,那size[x]!=mid
记得开ll偶

代码

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define ll long long
using namespace std;
const int maxn=100001;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
int ch[maxn][2],val[maxn],pri[maxn],siz[maxn],sz;
ll tot[maxn];
void update(int x) {
    siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];
    tot[x]=val[x]+tot[ch[x][0]]+tot[ch[x][1]];
}
int new_node(int v) {
    siz[++sz]=1;val[sz]=v;pri[sz]=rand();tot[sz]=v;
    return sz;
}
int merge(int x,int y) {
    if(!x||!y) return x+y;
    if(pri[x]<pri[y]) {
        ch[x][1]=merge(ch[x][1],y);
        update(x);
        return x;
    } else {
        ch[y][0]=merge(x,ch[y][0]);
        update(y);
        return y;
    }
}
void split(int now,int k,int &x,int &y) {
    if(!now) x=y=0;
    else {
        if(val[now]<=k)
            x=now,split(ch[now][1],k,ch[now][1],y);
        else
            y=now,split(ch[now][0],k,x,ch[now][0]);
        update(now);
    }
}
int k_th(int now,int k) {
    while(1) {
        if(k==siz[ch[now][0]]+1)return now;
        if(k<=siz[ch[now][0]]) now=ch[now][0];
        else k-=siz[ch[now][0]]+1,now=ch[now][1];
    }
}
int root,n,k,a[maxn];
void insert(int a) {
    int x,y;
    split(root,a,x,y);
    root=merge(merge(x,new_node(a)),y);
}
void delet(int a) {
    int x,y,z;
    split(root,a,x,z);
    split(x,a-1,x,y);
    y=merge(ch[y][0],ch[y][1]);
    root=merge(merge(x,y),z);
}
int main() {
    srand(time(NULL));
    n=read(),k=read();
    int mid=(k+1)>>1;
    pair<ll,pair<int,int> > pp;
    pp.first=0x3f3f3f3f3f3f3f3fLL;
    FOR(i,1,n) {
        a[i]=read();
        if(i<k) insert(a[i]);
        else {
            insert(a[i]);
            int x,y,get=k_th(root,mid);
            split(root,val[get],x,y);
            if(pp.first > ((ll)siz[x]*val[get]-(ll)tot[x]+(ll)tot[y]-(ll)siz[y]*val[get])) {
                pp.first=(ll)siz[x]*val[get]-(ll)tot[x]+(ll)tot[y]-(ll)siz[y]*val[get];
                pp.second.first=i;
                pp.second.second=val[get];
            }
            root=merge(x,y);
            delet(a[i-k+1]);
        }
    }
    cout<<pp.first<<"
";
    FOR(i,1,n) {
        if(i<=pp.second.first&&i>=pp.second.first-k+1)
            cout<<pp.second.second<<"
";
        else
            cout<<a[i]<<"
";
    }
    return 0;
}

以上是关于P3466 [POI2008]KLO-Building blocks的主要内容,如果未能解决你的问题,请参考以下文章

AC日记——[POI2008]BLO-Blockade 洛谷 [POI2008]BLO-Blockade

[POI2008]BLO

1123: [POI2008]BLO

3469 [POI2008]BLO-Blockade

BZOJ 1124[POI2008]枪战

BZOJ 1116: [POI2008]CLO