zoukankan      html  css  js  c++  java
  • bzoj1112 [POI2008]砖块Klo

    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

    Sample Output

    2

    HINT

    原题还要求输出结束状态时,每柱砖的高度.本题略去.

    很容易想到用个平衡树维护一段长为k的区间,每次区间右移就是加一个数再删一个数。

    题意是把区间全变成一个数,然后求Σ|a[i]-x|

    首先,把一段区间全变成中位数是最优的。这个可以自行脑补(一开始自己yy是平均数结果各种呵呵呵)

    ndsf:splay好做啊

    但是……总之我就是要用treap

    求中位数x简单,第(k/2+1)大就是了(其实不太放心然后x+1再跑了一遍,其实不+1应该也没错吧……)

    然后abs要分类讨论,要比它大的统计一次,比他小的统计一次

    我的做法是直接自顶向下递归找一下,就是细节啦

    以统计比它大的(upcalc(now,x))为例

    递归搜到一个节点,如果这个点比它小,或者和它相等,那么左子树和这个点都不用统计,只要处理它的右子树就好了

    如果这个点比它大,显然这个点和它的右子树都肯定比它大,直接推公式统计。左子树未定,递归搜下去

    第一次写维护平衡树的sum就写疵了……各种不知道哪里写错……一怒之下treap节点几个变量改longlong结果A了……

    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    #define LL long long
    struct treap{
    	int l,r,dat,rnd;
    	LL rep,son;
    	LL sum;
    }tree[500000];
    int a[100010];
    int n,k,treesize,root;
    LL tot,ans=1LL<<40;
    inline LL min(LL a,LL b)
    {return a<b?a:b;}
    inline void update(int k)
    {
    	tree[k].sum=(LL)tree[tree[k].l].sum+tree[tree[k].r].sum+tree[k].dat*tree[k].rep;
    	tree[k].son=tree[tree[k].l].son+tree[tree[k].r].son+tree[k].rep;
    }
    inline void right_rotate(int &k)
    {
    	int t=tree[k].l;
    	tree[k].l=tree[t].r;
    	tree[t].r=k;
    	tree[t].sum=tree[k].sum;
    	tree[t].son=tree[k].son;
    	update(k);
    	k=t;
    }
    inline void left_rotate(int &k)
    {
    	int t=tree[k].r;
    	tree[k].r=tree[t].l;
    	tree[t].l=k;
    	tree[t].sum=tree[k].sum;
    	tree[t].son=tree[k].son;
    	update(k);
    	k=t;
    }
    inline void insert(int &now,int x)
    {
    	if (!now)
    	{
    		now=++treesize;
    		tree[now].rnd=rand();
    		tree[now].son=tree[now].rep=1;
    		tree[now].dat=x;
    		tree[now].sum=(LL)x;
    		return;
    	}
    	tree[now].son++;
    	int data=tree[now].dat;
    	if (x==data)
    	{
    		tree[now].rep++;
    		tree[now].sum+=tree[now].dat;
    		return;
    	}
    	if (x<data)
    	{
    		insert(tree[now].l,x);
    		if (tree[tree[now].l].rnd>tree[now].rnd)right_rotate(now);
    	}else
    	{
    		insert(tree[now].r,x);
    		if (tree[tree[now].r].rnd>tree[now].rnd)left_rotate(now);
    	}
    	update(now);
    }
    inline void del(int &now,int x)
    {
    	if (!now)return;
    	int num=tree[now].dat;
    	if (x==num)
    	{
    		if (tree[now].rep>1)
    		{
    			tree[now].rep--;
    			tree[now].son--;
    			tree[now].sum-=tree[now].dat;
    			return;
    		}
    		if (tree[now].l*tree[now].r==0)now=tree[now].l+tree[now].r;
    		else
    		{
    			if (tree[tree[now].l].rnd>tree[tree[now].r].rnd)
    			{
    				right_rotate(now);
    				del(now,x);
    			}else
    			{
    				left_rotate(now);
    				del(now,x);
    			}
    		}
    	}else
    	{
    		tree[now].son--;
        	if (x<num)del(tree[now].l,x);
    		else del(tree[now].r,x);
    	}
    	update(now);
    }
    inline int find(int now,int x)
    {
        if(!now)return 0;
        if(x<=tree[tree[now].l].son)return find(tree[now].l,x);
        else if(x>tree[tree[now].l].son+tree[now].rep)
    	  return find(tree[now].r,x-tree[tree[now].l].son-tree[now].rep);
        else return tree[now].dat;
    }
    inline void upcalc(int now,int x)
    {
    	if (!now)return;
    	if (tree[now].dat<=x)upcalc(tree[now].r,x);
    	else
    	{
    		tot+=(LL)(tree[now].sum-tree[tree[now].l].sum)-x*(tree[now].son-tree[tree[now].l].son);
    		upcalc(tree[now].l,x);
    	}
    }
    inline void dncalc(int now,int x)
    {
    	if (!now)return;
    	if (tree[now].dat>=x)dncalc(tree[now].l,x);
    	else
    	{
    		tot+=(LL)x*(tree[now].son-tree[tree[now].r].son)-(tree[now].sum-tree[tree[now].r].sum);
    		dncalc(tree[now].r,x);
    	}
    }
    inline void calc(int now,int todel,int toadd)
    {
    	if(todel!=toadd)
    	{
    		insert(root,toadd);
    		del(root,todel);
    	}
    	int ave;
    	ave=find(root,k/2+1);
    	tot=0;
    	upcalc(root,ave);
    	dncalc(root,ave);
    	ans=min(ans,tot);
    	ave++;
    	tot=0;
    	upcalc(root,ave);
    	dncalc(root,ave);
    	ans=min(ans,tot);
    }	
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
    	n=read();k=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	for(int i=1;i<=k;i++)insert(root,a[i]);
    	calc(k,0,0);
    	for(int i=k+1;i<=n;i++)calc(i,a[i-k],a[i]);
    	printf("%lld",ans);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    java 应用使用jfr+sjk 生成应用火焰图
    使用btrace 分析java 应用
    vigil监控以及webhook使用
    honest-profiler+hprof2flamegraph 基础的扩展
    honest-profiler+hprof2flamegraph 查看java 应用火焰图信息
    Quark 基于electron 的跨平台应用开发ide
    nodejs 应用火焰图简单分析
    docker 中试用jfr
    使用foreman 管理基于Procfile 的应用
    xfs validation inode faild 问题解决
  • 原文地址:https://www.cnblogs.com/zhber/p/4035927.html
Copyright © 2011-2022 走看看