题意:
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.你还要求输出结束状态时,每柱砖的高度
题解:
很显然,要让我们将这K个柱子变成一样高并且操作次数最少,就是求这K个数的中位数
所以我们需要用一种数据结构能够实现插入,删除,求第k大,它前面有多少个数,后面有多少个数。
然后根据这K个数和中位数就能计算出最少次数了
找到中位数后就可以知道
左边可以通过将中位数伸展到根节点,然后求出比该数小的和及比它大的数的和即可
这里我用的是Splay,当然fhq,zkw线段树,主席树都行。有思路就好做了,接下来就是码农时间了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long LL;
const int MAXN = 1e5+10;
const int MOD = 998244353;
struct node{ int son[2],fa,cnt,sz,sum,val; }t[MAXN];
int root,tot,a[MAXN];
inline int id(int x){ return x==t[t[x].fa].son[1]; }
inline void pushup(int x){
t[x].sz = t[t[x].son[0]].sz+t[t[x].son[1]].sz+t[x].cnt;
t[x].sum = t[t[x].son[0]].sum + t[t[x].son[1]].sum+t[x].val*t[x].cnt;
}
inline void rotate(int x){
int y=t[x].fa,z=t[y].fa,k=id(x);
t[z].son[id(y)]=x; t[x].fa=z;
t[y].son[k]=t[x].son[k^1]; t[t[x].son[k^1]].fa=y;
t[x].son[k^1]=y; t[y].fa=x;
pushup(y); pushup(x);
}
inline void splay(int x,int pos){
while(t[x].fa!=pos){
int y=t[x].fa,z=t[y].fa;
if(z!=pos) id(x)==id(y) ? rotate(y):rotate(x);
rotate(x);
}
if(!pos) root=x;
}
inline void update(int u,int fa,int x){
t[u].cnt=t[u].sz=1;
t[u].fa=fa; t[u].sum=t[u].val=x;
}
inline void Insert(int x){
if(!root){
root=++tot;
update(root,0,x); return;
}
int u=root;
while(1){
t[u].sum += x; t[u].sz ++;
if(t[u].val==x) { t[u].cnt++; splay(u,0); return; }
int v = x>t[u].val;
if(!t[u].son[v]){
t[u].son[v]=++tot; update(t[u].son[v],u,x);
u=t[u].son[v]; splay(u,0); return;
}
u=t[u].son[v];
}
}
inline void del(int x){
int u=root;
while(t[u].val!=x) u=t[u].son[x>t[u].val];
splay(u,0);
t[u].cnt--; t[u].sz--; t[u].sum-=x;
if(t[u].cnt) return;
int nxt=t[u].son[1];
while(nxt && t[nxt].son[0]) nxt=t[nxt].son[0];
if(!nxt) { root=t[u].son[0]; t[root].fa=0; }
else{
splay(nxt,u);
t[nxt].son[0]=t[u].son[0];
t[t[u].son[0]].fa=nxt;
t[root=nxt].fa=0;
pushup(root);
}
}
inline int kth(int x){
int u=root;
while(1){
if(t[t[u].son[0]].sz>=x) u=t[u].son[0];
else{
if(t[t[u].son[0]].sz+1<=x && x<=t[t[u].son[0]].sz+t[u].cnt) return u;
x -= t[t[u].son[0]].sz+t[u].cnt;
u = t[u].son[1];
}
}
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
int n,k; scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=k;i++) Insert(a[i]);
int mid = (k+1)/2,ans = 1e18,l=0,r=0,tag=0;
for(int i=k;i<=n;i++){
int u=kth(mid);
splay(u,0);
int res = 0;
res = t[t[u].son[0]].sz*t[u].val-t[t[u].son[0]].sum+t[t[u].son[1]].sum-t[t[u].son[1]].sz*t[u].val;
if(res<ans){ ans=res; l=i-k+1; r=i; tag=t[u].val; }
del(a[i-k+1]);
if(i+1<=n) Insert(a[i+1]);
}
printf("%lld\n",ans);
for(int i=1;i<=n;i++)
if(i>=l && i<=r) printf("%lld\n",tag);
else printf("%lld\n",a[i]);
return 0;
}
来源:CSDN
作者:Nightmare丶
链接:https://blog.csdn.net/qq_43544481/article/details/103602689