zoukankan      html  css  js  c++  java
  • 线段树 || BZOJ 1112: [POI2008]砖块Klo

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1112

    题解:

    希望有连续K柱的高度是一样的,就先把1~K的数扔进线段树(线段树的下标就是数值,不需要离散化),求一波中位数和答案作为初始答案,

    再从第K+1到N扫一遍,依次把每个数扔进线段树同时把第i-K个树弄出来扔掉,不断求中位数和更新答案就好了。

    这里求序列中所有数到中位数的距离是这样求的:线段树多维护一个sum,当前序列中小于中位数的数的个数记为cnt1,

    和为sum1,大于中位数的数的个数记为cnt2,和为sum2。于是答案就很显然是:pt(即中位数)*cnt1-sum1+sum2-pt*cnt2。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define ll long long
     5 #define min(a,b) ((a)<(b)?(a):(b))
     6 using namespace std;
     7 const int maxn=100000+50,maxh=1000000+50,max_h=maxh-40;
     8 int N,K,Z;
     9 ll sum[2],H[maxn],ans,pt,cnt[2];
    10 inline ll rd(){
    11     ll x=0;int f=1;char c=getchar();
    12     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    13     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    14     return f*x;
    15 }
    16 struct Tree{
    17     int l,r;
    18     ll sum,cnt;
    19 }t[maxh<<2];
    20 inline void Build(int x,int l,int r){
    21     t[x].l=l;t[x].r=r;int mid=(l+r)>>1;
    22     if(l==r)return;
    23     Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
    24     return;
    25 }
    26 inline void Update(int x,int q,int o){
    27     int l=t[x].l,r=t[x].r,mid=(l+r)>>1;
    28     if(l==r&&l==q){
    29         if(o==1){t[x].sum+=l; t[x].cnt++;}
    30             else{t[x].sum-=l; t[x].cnt--;}
    31         return;
    32     }
    33     int ls=x<<1,rs=x<<1|1;
    34     if(q<=mid)Update(ls,q,o);else Update(rs,q,o);
    35     t[x].sum=t[ls].sum+t[rs].sum;
    36     t[x].cnt=t[ls].cnt+t[rs].cnt;
    37     return;
    38 }
    39 inline int Find(int x,int z){//寻找中位数 
    40     int l=t[x].l,r=t[x].r,ls=x<<1,rs=x<<1|1;
    41     if(l==r)return l;
    42     if(t[ls].cnt>=z)return Find(ls,z);else return Find(rs,z-t[ls].cnt);
    43 }
    44 inline void Work(int x,int ql,int qr,int o){
    45     int l=t[x].l,r=t[x].r,mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
    46     if(ql<=l&&r<=qr){
    47         sum[o]+=t[x].sum;
    48         cnt[o]+=t[x].cnt;
    49         return;
    50     }
    51     if(ql<=mid)Work(ls,ql,qr,o);
    52     if(qr>mid)Work(rs,ql,qr,o);
    53     return;
    54 }
    55 int main(){
    56     N=rd();K=rd();
    57     for(int i=1;i<=N;i++){H[i]=rd();H[i]++;}
    58     Build(1,1,max_h);
    59     for(int i=1;i<=K;i++)Update(1,H[i],1);
    60     Z=(K+1)>>1;
    61     pt=Find(1,Z);//pt即为中位数 
    62     sum[0]=sum[1]=cnt[0]=cnt[1]=0;
    63     Work(1,1,pt,0);Work(1,pt,max_h,1);
    64     ans=(cnt[0]*pt-sum[0])+(sum[1]-cnt[1]*pt);
    65     for(int i=K+1;i<=N;i++){
    66         Update(1,H[i-K],2);Update(1,H[i],1);
    67         pt=Find(1,Z);
    68         sum[0]=sum[1]=cnt[0]=cnt[1]=0;
    69         Work(1,1,pt,0);Work(1,pt,max_h,1);
    70         if(ans>(cnt[0]*pt-sum[0])+(sum[1]-cnt[1]*pt)){
    71             ans=(cnt[0]*pt-sum[0])+(sum[1]-cnt[1]*pt);
    72         }
    73     }
    74     printf("%lld
    ",ans);
    75     return 0;
    76 }

    By:AlenaNuna

  • 相关阅读:
    无限维
    黎曼流形
    why we need virtual key word
    TOJ 4119 Split Equally
    TOJ 4003 Next Permutation
    TOJ 4002 Palindrome Generator
    TOJ 2749 Absent Substrings
    TOJ 2641 Gene
    TOJ 2861 Octal Fractions
    TOJ 4394 Rebuild Road
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/10432762.html
Copyright © 2011-2022 走看看