zoukankan      html  css  js  c++  java
  • P4552 [Poetize6] IncDec Sequence 题解

    原题链接

    简要题意:

    给定长度为 \(n\) 的序列 \(\{a_i\}\),每次操作可以将任一区间 \([l,r]\) 的所有数加一(或减一),求至少多少次操作可以让序列中所有数相同。并且在保证最小操作数的情况下求相同的数的可能个数(即末状态数)。

    \(n \leq 10^5\).

    区间操作往往可以转换为差分操作。

    注意到,如果我们令 \(\{c_i\}\)\(\{a_i\}\) 的差分数组,也就是:

    \[\begin{cases} c_1 = a_1 \\ c_k = a_k - a_{k-1} (\forall k \in [2,n]) \\ \end{cases}\]

    那么,这个时候,对于 \(\{a_i\}\) 中,\([l,r]\) 区间的 \(+1\) 操作,可以简化为:

    \[\begin{cases} c_{l} \leftarrow c_{l} + 1 \\ c_{r+1} \leftarrow c_{r+1} - 1 \\ \end{cases}\]

    同理 \(-1\) 操作可以简化为:

    \[\begin{cases} c_{l} \leftarrow c_{l} - 1 \\ c_{r+1} \leftarrow c_{r+1} + 1 \\ \end{cases}\]

    同时我们发现,\(\{a_i\}\) 全相等时,\(\{c_i\}\)\(c_1 = a_1\) 外全为 \(0\),于是题意转为:

    给定一个长度为 \(n\) 的序列 \(\{c_i\}\),每次操作可以选定任意的 \(l,r\) 并将 \(c_l\)\(c_r\) 一个加一,一个减一。求能使得 \(c_2 \cdots c_n\) 全部变为 \(0\) 的最少操作数,以及变化后 \(c_1\) 可能的值的个数。

    这里,答案已经呼之欲出了。

    很显然,我们应该尽量把一个负数 \(c_x\) 和一个正数 \(c_y\) 同时进行 “绝对值逼近 \(0\)” 的加减操作,通过 \(\min(c_x,c_y)\) 次可以得到 \(0\). 于是我们将所有正数的和记为 \(p\),负数的 绝对值 的和记为 \(q\),显然,想要消灭所有正数(或负数)需要 \(\min(p,q)\) 次。而对于剩下的数,我们可以将其和 \(c_1\) 进行加减操作。于是第一问答案为 \(\max(p,q)\),这是十分明显的。

    考虑第二问。注意到,需要满足最小操作数,因此 “绝对值逼近 \(0\)” 的加减操作 是不可能改变 \(c_1\) 的。但是注意到,最后对于剩下的数,当只剩下一个数 \(c_n \not = 0\) 的时候(注意一定是 \(n\)),我们就可以不一定选定 \([1,x]\) 操作。可以直接选定 \([n,n+1]\) 进行操作(想象你变化原数组末位的时候,后面一位的差分值也会变),而不是改变 \(c_1\). 也只有在这个时候才能在保证最小操作数的情况下使得 \(c_1\) 有更多可能性。此时 \(|c_n| = |p-q|\) 显然。

    于是第二问答案为 \(|p-q|+1\).

    时间复杂度:\(\mathcal{O}(n)\).

    代码实现中,差分利用滚动一波过去了。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+1;
    typedef long long ll;
    
    int n;
    ll p,q;
    
    int main() {
    	scanf("%d",&n);
    	int x; scanf("%d",&x);
    	for(int i=2;i<=n;i++) {
    		int y; scanf("%d",&y);
    		if(y>x) p+=y-x;
    		else q+=x-y;
    		x=y;
    	}
    	printf("%lld\n%lld\n",max(p,q),abs(p-q)+1);
    	return 0;
    }
    
    简易的代码胜过复杂的说教。
  • 相关阅读:
    Python 安装Twisted 提示python version 2.7 required,which was not found in the registry
    Openfire Strophe开发中文乱码问题
    css div 垂直居中
    How to create custom methods for use in spring security expression language annotations
    How to check “hasRole” in Java Code with Spring Security?
    Android 显示/隐藏 应用图标
    Android 当媒体变更后,通知其他应用重新扫描
    文件上传那些事儿
    专题:点滴Javascript
    主流动画实现方式总结
  • 原文地址:https://www.cnblogs.com/bifanwen/p/15733755.html
Copyright © 2011-2022 走看看