bzoj1112: [POI2008]砖块Klo(主席树)

3人阅读 评论(1) 收藏 举报
分类:

题目传送门

解法:
比赛的时候不知道怎么就一直在想主席树(可能最近做主席树有点多)
然后什么线段树啊树状数组都没想过。
然后就被师兄强行40M卡空间全爆了。。
大视野还是有良心的啊162M。。

就用主席树求出中位数,然后没了。

代码实现:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node {int c,lc,rc;ll s;}t[2000010];int cnt,rt[110000];
void build(int &u,int l,int r,int p,int s) {
    if(u==0)u=++cnt;t[u].c++;t[u].s+=(ll)s;
    if(l==r)return ;int mid=(l+r)/2;
    if(p<=mid)build(t[u].lc,l,mid,p,s);
    else build(t[u].rc,mid+1,r,p,s);
}
void Merge(int &u1,int u2) {
    if(u1==0) {u1=u2;return ;}if(u2==0)return ;
    t[u1].c+=t[u2].c;t[u1].s+=t[u2].s;
    Merge(t[u1].lc,t[u2].lc);Merge(t[u1].rc,t[u2].rc);
}
int find_mid(int &u1,int &u2,int l,int r,int k) {
    if(l==r)return l;int mid=(l+r)/2;
    int c=t[t[u1].lc].c-t[t[u2].lc].c;
    if(k<=c)return find_mid(t[u1].lc,t[u2].lc,l,mid,k);
    else return find_mid(t[u1].rc,t[u2].rc,mid+1,r,k-c);
}
int find_lc(int &u1,int &u2,int l,int r,int p) {
    if(t[u1].c-t[u2].c==0)return 0;
    if(l==r) return t[u1].c-t[u2].c;int mid=(l+r)/2;
    if(p<=mid)return find_lc(t[u1].lc,t[u2].lc,l,mid,p);
    else return find_lc(t[u1].rc,t[u2].rc,mid+1,r,p)+t[t[u1].lc].c-t[t[u2].lc].c;
}
ll find_ls(int &u1,int &u2,int l,int r,int p) {
    if(t[u1].s-t[u2].s==0) return 0;
    if(l==r)return t[u1].s-t[u2].s;int mid=(l+r)/2;
    if(p<=mid)return find_ls(t[u1].lc,t[u2].lc,l,mid,p);
    else return find_ls(t[u1].rc,t[u2].rc,mid+1,r,p)+t[t[u1].lc].s-t[t[u2].lc].s;
}
struct edge {int x,id;}a[110000];ll s[110000];
bool cmp(edge n1,edge n2){return n1.x<n2.x;}
bool cmp1(edge n1,edge n2){return n1.id<n2.id;}
int main() {
    //freopen("akc.in","r",stdin);freopen("akc.out","w",stdout);
    int n,k;scanf("%d%d",&n,&k);int mmax=0;
    for(int i=1;i<=n;i++) {scanf("%d",&a[i].x);a[i].id=i;}
    if(k==1){printf("0\n");return 0;}
    sort(a+1,a+1+n,cmp);int tot=0;a[0].x=-1;int tt=0;
    for(int i=1;i<=n;i++) if(a[i].x!=a[i-1].x)tt++;
    for(int i=1;i<=n;i++) {if(a[i].x!=a[i-1].x)tot++;build(rt[a[i].id],1,tt,tot,a[i].x);s[tot]=a[i].x;}
    for(int i=1;i<=n;i++) Merge(rt[i],rt[i-1]);
    sort(a+1,a+1+n,cmp1);ll T=0;for(int i=1;i<k;i++)T+=ll(a[i].x);ll Ans=ll(100000000000);a[0].x=0;
    for(int i=k;i<=n;i++) {
        T+=ll(a[i].x);T-=ll(a[i-k].x);
        int p=find_mid(rt[i],rt[i-k],1,tt,(k+1)/2);
        int lc=find_lc(rt[i],rt[i-k],1,tt,p),rc=k-lc;
        ll ls=find_ls(rt[i],rt[i-k],1,tt,p),rs=T-ls;
        Ans=min(Ans,ll(lc*s[p])-ls+rs-ll(rc*s[p]));
    }printf("%lld\n",Ans);
    return 0;
}
查看评论

BZOJ 1112 [POI2008]砖块Klo Treap

BZOJ 1112 [POI2008]砖块Klo Treap
  • wzq_QwQ
  • wzq_QwQ
  • 2015-09-14 20:17:03
  • 1071

bzoj-1112 砖块Klo

题意: 给出一个长度为n的数列,现要将其连续k个数变成一样的; 每次可以对一个数+1或-1,问最小操作次数; 1 题解: 感觉是一道好题吧; 首先有这样一个结论:将这些数置为中位数...
  • ww140142
  • ww140142
  • 2015-09-15 07:42:17
  • 1338

bzoj1112 POI2008 砖块Klo 树状数组

fuxey必须%。。。 树状数组的话,其实就是相当于滑动窗口,然后用树状数组维护当前中位数,总和用前缀和搞一下,就可以直接算了。#include #include #include #include...
  • qq_35866453
  • qq_35866453
  • 2017-04-27 09:25:44
  • 136

Bzoj1112:[POI2008]砖块Klo:splay

题目链接:1112:[POI2008]砖块Klo 原题目是要输出最终高度的,代码中有体现 显然一段区间都变成某个数且代价最小,那么就变成中位数 所以我们维护中位数即可,上splay 一不小心把树建反成...
  • qq_34025203
  • qq_34025203
  • 2016-04-08 10:07:59
  • 307

bzoj1112【poi2008】砖块klo

平衡树
  • AaronGZK
  • AaronGZK
  • 2015-11-24 23:54:17
  • 1006

[POI2008]砖块Klo

那么问题就在于如何找任意区间的中位数 划分树和平衡树都可以解决 所以是水题一道…… 下面描述我的悲惨经历…… 上周周末就看到了这道题 觉得应该可以用划分树水过 屁颠屁颠写了个划分树,写到一...
  • OrpineX
  • OrpineX
  • 2012-01-10 19:42:17
  • 1229

[主席树] BZOJ1112: [POI2008]砖块Klo

水题。直接主席树求区间中位数,然后中位数左边右边求sum和cnt。算一下就好了。#include #include #define mp(x,y) make_pair(x,y) #define Fir...
  • CHHNZ
  • CHHNZ
  • 2017-09-29 09:59:01
  • 124

BZOJ 1112 POI2008 砖块

POI , 树状数组
  • Fuxey
  • Fuxey
  • 2016-02-10 15:49:32
  • 656

bzoj 1112 [POI2008]砖块Klo

DescriptionN柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数...
  • mars_ch
  • mars_ch
  • 2016-11-04 17:36:02
  • 125

bzoj1112 [POI2008]砖块Klo(平衡树/map/树状数组)

把一个区间的数都变成一个数,显然都变成中位数需要的次数最少,而次数就是后k/2的数的和-前k/2的数的和,因此原问题就是求区间中位数。区间中位数可以平衡树来搞,也可以用stl水过hh。先把1…k排序,...
  • Icefox_zhx
  • Icefox_zhx
  • 2017-11-09 16:30:10
  • 109
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 2350
    排名: 1万+
    博客专栏
    最新评论