zoukankan      html  css  js  c++  java
  • BZOJ1367:[Baltic2004]sequence

    浅谈左偏树:https://www.cnblogs.com/AKMer/p/10246635.html

    题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=1367

    显然,如果给出的数组是递增的,那么答案就是(0)

    如果给出的数组是递减的,根据贪心的思想答案就是(sumlimits_{i=1}^{n}|x-t_i|)(x)(t)数组的中位数。

    但是给出的数组是无序的。

    我们可以把这个数组划成一段段的,每一段都选一个(x)去当做中位数。简单的来讲,最优的方案是(z_i=t_i)的,但是为了保证(z)数组的递增性我们必须要把比前一位小的(z)和前一位合并到一段里去,形成新的一段,然后这一段的(z)就是这一段(t)的中位数。

    但是这样出现了重复的(z),不满足严格递增的性质。但是我们只需要把(t_i=t_i-i)就行了。这样就默认是严格递增的了。

    时间复杂度:(O(nlogn))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int maxn=1e6+5;
    
    ll ans;
    int n,tot,cnt;
    int l[maxn],r[maxn];
    int fa[maxn],dist[maxn],son[maxn][2];
    int a[maxn],rt[maxn],val[maxn],siz[maxn];
    
    int read() {
    	int x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
    
    int newnode(int v) {
    	val[++tot]=v;
    	siz[tot]=1;return tot;
    }
    
    int merge(int a,int b) {
    	if(!a||!b)return a+b;
    	if(val[a]<val[b])swap(a,b);
    	son[a][1]=merge(son[a][1],b);
    	if(dist[son[a][1]]>dist[son[a][0]])
    		swap(son[a][1],son[a][0]);
    	dist[a]=dist[son[a][1]]+1;
    	siz[a]=siz[son[a][0]]+1+siz[son[a][1]];
    	return a;
    }
    
    int pop(int u) {
    	int res=merge(son[u][0],son[u][1]);
    	son[u][0]=son[u][1]=0;
    	return res;
    }
    
    int main() {
    	n=read(),dist[0]=-1;
    	for(int i=1;i<=n;i++)
    		a[i]=read()-i;
    	for(int i=1;i<=n;i++) {
    		rt[++cnt]=newnode(a[i]);l[cnt]=r[cnt]=i;
    		while(cnt>1&&val[rt[cnt]]<val[rt[cnt-1]]) {
    			rt[cnt-1]=merge(rt[cnt-1],rt[cnt]);r[--cnt]=i;
    			while(siz[rt[cnt]]>(r[cnt]-l[cnt]+2)/2)rt[cnt]=pop(rt[cnt]);
    		}
    	}
    	for(int i=1;i<=cnt;i++)
    		for(int j=l[i];j<=r[i];j++)
    			ans+=abs(val[rt[i]]-a[j]);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    码农提高工作效率 (转)
    Python快速教程 尾声
    C#基础——谈谈.NET异步编程的演变史
    [C#]動態叫用Web Service
    零极限 核心中的核心和详解
    项目经理应该把30%的时间用在编程上
    高效能程序员的七个习惯
    我们如何进行代码审查
    工作经常使用的SQL整理,实战篇(二)
    C# Socket网络编程精华篇 (转)
  • 原文地址:https://www.cnblogs.com/AKMer/p/10250719.html
Copyright © 2011-2022 走看看