题解: 一眼错误写法....拿平均数去当了标准 队友YY说可以中位数 然后我们可以通过主席树来维护区间第K大 以及小于他的和以及大于它的的和 然后窗口滑动取最小即可
/**************************************************************
Problem: 1112
User: c20161007
Language: C++
Result: Accepted
Time:3832 ms
Memory:86056 kb
****************************************************************/
#include <bits/stdc++.h>
#define ll long long
const int MAXN=1e5+10;
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
vector<int>vec;
typedef struct node{
int l,r;ll sum;int num;
}node;
node d[MAXN*42];int rt[MAXN];
int cnt;
void built(int &x,int y,int l,int r,int t,ll vul){
x=++cnt;d[x]=d[y];d[x].sum+=vul;d[x].num++;
if(l==r)return ;
int mid=(l+r)>>1;
if(t<=mid)built(d[x].l,d[y].l,l,mid,t,vul);
else built(d[x].r,d[y].r,mid+1,r,t,vul);
}
ll ans;int ans1;
void querty(int x,int y,int l,int r,int t){
if(l==r){ans+=d[y].sum-d[x].sum;ans1+=d[y].num-d[x].num;return ;}
int mid=(l+r)>>1;
if(t>mid)ans+=(d[d[y].l].sum-d[d[x].l].sum),ans1+=d[d[y].l].num-d[d[x].l].num,querty(d[x].r,d[y].r,mid+1,r,t);
else querty(d[x].l,d[y].l,l,mid,t);
}
int ans2;
void querty1(int x,int y,int l,int r,int t){
if(l==r){ans2=l;return ;}
int mid=(l+r)>>1;
if(d[d[y].l].num-d[d[x].l].num>=t)querty1(d[x].l,d[y].l,l,mid,t);
else querty1(d[x].r,d[y].r,mid+1,r,t-(d[d[y].l].num-d[d[x].l].num));
}
int n,k;ll a[MAXN];
ll sum[MAXN];
int main(){
n=read();k=read();
for(int i=1;i<=n;i++)a[i]=read(),vec.push_back(a[i]),sum[i]=sum[i-1]+a[i];
// for(int i=k;i<=n;i++)vec.push_back((ll)((sum[i]-sum[i-k])/k));
sort(vec.begin(),vec.end());
int sz=unique(vec.begin(),vec.end())-vec.begin();
for(int i=1;i<=n;i++)a[i]=lower_bound(vec.begin(),vec.begin()+sz,a[i])-vec.begin()+1;
for(int i=1;i<=n;i++)built(rt[i],rt[i-1],1,sz,a[i],vec[a[i]-1]);
ll cnt=9e18;ll t2,t3;int t1,t4;int ans3;
for(int i=k;i<=n;i++){
//int t1=lower_bound(vec.begin(),vec.begin()+sz,((sum[i]-sum[i-k])/k))-vec.begin()+1;
if(k%2)querty1(rt[i-k],rt[i],1,sz,k/2+1),t1=vec[ans2-1];
else querty1(rt[i-k],rt[i],1,sz,k/2),t1=vec[ans2-1],querty1(rt[i-k],rt[i],1,sz,k/2+1),t1+=vec[ans2-1],t1/=2;
// cout<<t1<<endl;
ans3=t1;
t4=lower_bound(vec.begin(),vec.begin()+sz,t1)-vec.begin()+1;
if(vec[t4-1]!=t1)t4--;
t1=t4;
ans=0;
//cout<<(sum[i]-sum[i-k])/k<<endl;
ans1=0;
querty(rt[i-k],rt[i],1,sz,t1);
// cout<<ans<<" "<<ans1<<endl;
t2=1ll*ans1*ans3-ans;
t3=sum[i]-sum[i-k]-ans;
ans1=k-ans1;
t3-=1ll*ans1*ans3;
cnt=min(cnt,t2+t3);
}
printf("%lld\n",cnt);
return 0;
}
1112: [POI2008]砖块Klo
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2479 Solved: 883
[Submit][Status][Discuss]
Description
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.
Input
第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000
Output
最小的动作次数
Sample Input
5 3
3
9
2
3
1
3
9
2
3
1
Sample Output
2
HINT
原题还要求输出结束状态时,每柱砖的高度.本题略去.