zoukankan      html  css  js  c++  java
  • 题解 P4331 【[BalticOI 2004]Sequence 数字序列】

    题目链接

    Solution [BalticOI 2004]Sequence 数字序列

    题目大意:给定一个长为 (n) 的整数序列 (a),你需要构造出一个序列 (b),满足 (forall i in [1,n)quad b_i<b_{i+1}),在这个前提下,使得 (sum |a_i-b_i|) 最小

    可并堆,思维


    分析:

    有一个结论可以将严格递增变为不降。

    考虑对于位置 (i,j),它们之间都是严格单调递增的,那么有(b_j-b_i geq j-i)

    移项发现,将每个位置的数减去它们的下标,就转化为求一个不降的序列 (b)

    有个十分暴力的 (dp),设 (f[i][j]) 表示构造 (b) 的前 (i) 个数,第 (i) 个数不超过 (j) 的最小代价和

    (f[i][j]=min{f[i-1][k]+|a_i-k|})

    由归纳法可以证明,对于一个位置 (i),我们的决策相当于是在求

    (|x-a_1|+|x-a_2|+cdots|x-a_i|) 这个东西的最小值

    由它的几何意义,我们可以知道取中位数最优。

    但是全局取一个中位数作为 (b) 不一定是最优解,因为我们可以还可以将 (a) 划分为许多段,每段取一个中位数作为这一段的 (b),只要满足 (b) 单调不降就可以了

    这个东西可以用一个大根堆来维护,因为求一个长为 (len) 的序列的中位数,就相当于求它的第 (lceil frac{len}{2} ceil)

    那么我们开一个栈,每个元素是一个堆。每次插入一个元素 (a),就看看它作为中位数是否满足单调不降,不满足就弹栈,合并了再压回去。用左偏树来实现就可以了。

    #include <cstdio>
    #include <cctype>
    #include <stack>
    #include <utility>
    #include <algorithm>
    #pragma GCC optmize(2)
    using namespace std;
    typedef long long ll;
    constexpr int maxn = 1e6 + 100,inf = 0x7fffffff;
    struct IO{//-std=c++11,with cstdio and cctype
    	private:
    		static constexpr int ibufsiz = 1 << 20;
    		char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
    		static constexpr int obufsiz = 1 << 20;
    		char obuf[obufsiz + 1],*onow = obuf;
    		const char *oed = obuf + obufsiz;
    	public:
    		inline char getchar(){
    			#ifndef ONLINE_JUDGE
    				return ::getchar();
    			#else
    				if(inow == ied){
    					ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
    					*ied = '';
    					inow = ibuf;
    				}
    				return *inow++;
    			#endif
    		}
    		template<typename T>
    		inline void read(T &x){
    			static bool flg;flg = 0;
    			x = 0;char c = getchar();
    			while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
    			while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    			if(flg)x = -x;
    		}
    		template <typename T,typename ...Y>
    		inline void read(T &x,Y&... X){read(x);read(X...);}
    		inline int readi(){static int res;read(res);return res;}
    		inline long long readll(){static long long res;read(res);return res;}
    		
    		inline void flush(){
    			fwrite(obuf,sizeof(char),onow - obuf,stdout);
    			fflush(stdout);
    			onow = obuf;
    		}
    		inline void putchar(char c){
    			#ifndef ONLINE_JUDGE
    				::putchar(c);
    			#else
    				*onow++ = c;
    				if(onow == oed){
    					fwrite(obuf,sizeof(char),obufsiz,stdout);
    					onow = obuf;
    				}
    			#endif
    		}
    		template <typename T>
    		inline void write(T x,char split = ''){
    			static unsigned char buf[64];
    			if(x < 0)putchar('-'),x = -x;
    			int p = 0;
    			do{
    				buf[++p] = x % 10;
    				x /= 10;
    			}while(x);
    			for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
    			if(split != '')putchar(split);
    		}
    		inline void lf(){putchar('
    ');}
    		~IO(){
    			fwrite(obuf,sizeof(char),onow - obuf,stdout);
    		}
    }io;
    template <typename A,typename B>
    inline void chkmin(A &x,const B &y){if(y < x)x = y;}
    template <typename A,typename B>
    inline void chkmax(A &x,const B &y){if(y > x)x = y;}
    
    int n,a[maxn],b[maxn];
    struct node{
    	int ls,rs,v,dis,siz;
    }tr[maxn];
    inline int merge(int x,int y){
    	if(!x || !y)return x | y;
    	if(tr[x].v < tr[y].v)swap(x,y);
    	tr[x].rs = merge(tr[x].rs,y);
    	if(tr[tr[x].ls].dis < tr[tr[x].rs].dis)swap(tr[x].ls,tr[x].rs);
    	tr[x].dis = tr[tr[x].rs].dis + 1;
    	tr[x].siz = tr[tr[x].ls].siz + tr[tr[x].rs].siz + 1;
    	return x;
    }
    stack<pair<int,int>> stk;
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("fafa.in","r",stdin);
    #endif
    	io.read(n);
    	for(int i = 1;i <= n;i++)
    		io.read(a[i]),a[i] -= i;
    	for(int i = 1;i <= n;i++){
    		tr[i].v = a[i],tr[i].siz = 1;
    		auto now = make_pair(i,1);
    		while(!stk.empty() && tr[stk.top().first].v > tr[now.first].v){
    			now.second += stk.top().second;
    			now.first = merge(now.first,stk.top().first);
    			stk.pop();
    			while(tr[now.first].siz > ((now.second + 1) >> 1))now.first = merge(tr[now.first].ls,tr[now.first].rs);
    		}
    		stk.push(now);
    	}
    	int pos = n;
    	while(!stk.empty()){
    		auto now = stk.top();stk.pop();
    		while(now.second--)b[pos--] = tr[now.first].v;
    	}
    	ll ans = 0;
    	for(int i = 1;i <= n;i++)ans += abs((ll)a[i] - b[i]);
    	io.write(ans,'
    ');
    	for(int i = 1;i <= n;i++)io.write(b[i] + i,' ');
    	io.lf();
    	return 0;
    }
    
  • 相关阅读:
    量子力学与广义相对论的统一——用广义相对论解释海森堡测不准原理 Unification of Quantum Mechanics and General Relativity: Explaining Heisenberg Uncertainty Principle with General Relativity
    用光的微粒说和广义相对论来解释衍射现象 Explanation of Diffraction Phenomenon by Particle Theory of Light and General Relativity
    质量能量等效的泛化--物理学定律方程与等效原理的对应关系 Generalization of Mass-Energy Equivalence--Corresponding Relations between Equations of Physical Laws and Equiva
    关于质能等效的两个思想实验 Two Ideological Experiments on Mass-Energy Equivalence
    购物商城Web开发第十七天
    购物商城Web开发第十六天
    购物商城Web开发第十五天
    购物商城Web开发第十四天
    购物商城Web开发第十三天
    暑假周总结二
  • 原文地址:https://www.cnblogs.com/colazcy/p/14074645.html
Copyright © 2011-2022 走看看