首页 > 其他分享 >Atcoder ABC307_G-Approximate Equalization 序列dp

Atcoder ABC307_G-Approximate Equalization 序列dp

时间:2023-08-08 21:44:27浏览次数:46  
标签:Atcoder int ABC307 Equalization Approximate leq ave sum dp

AT_ABC307_G-Approximate Equalization


没想到还有Approximate Equalization II !!:AT_ABC313_C

Description:

  • 给定一个长度为 \(N\) 的数列:\(A = (A_1,A_2,···,A_N)\),有两种操作可以以任意顺序进行任意多次(可以为0):
  • \(A[i]-\)=\(1\) 且 \(A[i+1]+\)=\(1\),\((1\leq i \leq N-1)\)
  • \(A[i]+\)=\(1\) 且 \(A[i+1]-\)=\(1\),\((1\leq i \leq N-1)\)
  • 求出使得数列 \(A\) 满足 \(\forall (i,j),|A_i-A_j|\leq 1\) 所需的最少操作次数。

Constraints:

  • \(2 \leq N \leq 5000\)
  • \(-10^9 \leq A_i \leq 10^9\)

Analysis:

  • 无论如何操作,\(sum=\sum A_i\) 恒为定值,则操作方向为让数列趋向于平均值 \(ave\),进一步细化,则终态数列 \(B\) 仅由 \(ave\) 和 \(ave+1\),且分别的个数可求 \((x,y)\)。

法一:

\[\left\{ \begin{aligned} &y = sum \% n \\ &x = n-y \end{aligned} \right. \]

法二:

\[\left\{ \begin{aligned} &x+y = n \\ &x\times res+y\times (res+1)=sum=\sum{A_i} \end{aligned} \right. \]

  • 发现 \(n\) 的范围并不大,结合终态每转换一位仅有两种状态,故可考虑序列\(dp\),复杂度 \(O(n^2)\)
  • \(dp[i][j]\) 表示前 \(i\) 个数中有 \(j\) 个 \((ave+1)\) 的最小操作数,此时有 \((i-j)\) 个 \(ave\)
  • 状态转移:因为问题中每次操作都是将 \(i\) 和 \(i+1\) 捆绑修改,现在我们考虑前 \(i\) 个数操作,最多影响区间 \([1,i+1]\),显然前 \(i+1\) 个数的总和不变,已知原来前 \(i+1\) 个数的和(当然使用前缀和来维护),同时结合目前的 \(dp\) 状态,我们知道已经有了 \(i-j\) 个 \(ave\) 和 \(j\) 个 \((ave+1)\),所以便可求得改变后的 \(a_{i+1}\)
    即\(new\_a=pre[i+1]-(i-j)\times ave-j\times (ave+1)\)
    则新增的操作数即为 \(op_1=|new\_a-ave|\) 或 \(op_2=|new\_a-(ave+1)|\)
  • 转移方程:
    \(dp[i+1][j]=min \{dp[i][j]+op_1,dp[i+1][j]\}\)
    \(dp[i+1][j+1]=min \{dp[i][j]+op_2,dp[i+1][j+1]\}\)
  • 代码细节要注意:!!
    1. c++对于 负数 整除和取模的处理需要微调一下(不像python...),例如\(-3 \div 5=0\neq -1...\) \(-3\%5=-3\neq2\)
    2. 不开long long 见祖宗(绷绷绷

Solution:

ll dp[maxn][maxn];
ll sum;
void solve() {
	int n; cin >> n;
	vector<ll> a(n+1),pre(n+1);
	for(int i=1;i<=n;i++) {
		cin >> a[i];
		sum += a[i];
		pre[i] = pre[i-1] + a[i];
	}
	ll ave = sum / n;
	if(ave * n > sum) ave--;
	int y = sum - ave * n; // ave+1
	int x = n - y; // ave
	
	memset(dp,0x3f,sizeof(dp));
	dp[0][0] = 0;
	
	for(int i=0;i<=n-1;i++) {
		for(int j=0;j<=i;j++) {
			ll val = (i-j)*ave+j*(ave+1);
			ll new_a = pre[i+1] - val;
			dp[i+1][j] = min(dp[i][j]+abs(new_a-ave),dp[i+1][j]);
			dp[i+1][j+1] = min(dp[i][j]+abs(new_a-(ave+1)),dp[i+1][j+1]);
		}
	}
	cout << dp[n][y] << endl;
}

标签:Atcoder,int,ABC307,Equalization,Approximate,leq,ave,sum,dp
From: https://www.cnblogs.com/Trilliverse/p/17615217.html

相关文章

  • AtCoder-ARC073_A Sentou
    Sentou【题意】:有一个开关,当按下开关后的T秒内会一直放水,当在放水状态时,如果有人再次按下开关,那么停止放水,并从按下的那一刻起的T秒会再次一直放水,给出n个人按压开关的时间,问总共流出多少水【思路】:简单模拟#include<bits/stdc++.h>usingnamespacestd;typedeflon......
  • AtCoder Beginner Contest 313
    AtCoderBeginnerContest313A-ToBeSaikyo思路:找到最大的,和第一个比较#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong//#defineint__int128#definedoublelongdoubletypedefpair<int,int>PII;typedefpair<string,int>PSI;t......
  • AtCoder Beginner Contest 313
    AtCoderBeginnerContest313-AtCoderA-ToBeSaikyo(atcoder.jp)从\(a_1\dotsa_{n-1}\)找出最大值与\(a_0\)比较即可#include<bits/stdc++.h>#defineintlonglong#defineendl'\n'usingnamespacestd;signedmain(){ios::sync_with_st......
  • 取数游戏 Atcoder-abc128_d
    枚举两端取了几个数,将手中的负数从小到大放回序列即可#include<bits/stdc++.h>usingnamespacestd;intn,m,a[55],c[55],ans=-0x7fffffff;intmain(){scanf("%d%d",&n,&m);for(inti=1;i<=n;i++)scanf("%d",&a[i]);f......
  • Atcoder Grand Contest 058 F - Authentic Tree DP
    考虑给\(f(T)\)赋予组合意义。一个直观的想法是,在每条边中间新建一个节点,然后每次选择一条边对应的点,然后把它删掉,递归剩余的两个部分,但是你会发现这样分母不对,应该是\(n\)但在这个模型里只有\(n-1\)。考虑魔改这个模型。我们在每个边对应的点下面添加\(998244352\)个点,你......
  • Atcoder ABC313_C-Approximate Equalization 2
    AT_ABC313_C-ApproximateEqualization2Description:给定一个整数序列\(A=(A_1,A_2,···,A_n)\),可以做以下操作任意次(可能为0):选择一个整数对\((i,j)\)\((1\leqi,j\leqn)\),使得\(A[i]-\)=\(1\),\(A[j]+\)=\(1\),求出使得数列\(A\)中的\(max-min\leq1\)所需的最少......
  • Atcoder Beginner Contest 313
    CDEF有\(n(1\len\le40)\)张牌,每一张牌正面写上了数字\(a_i\),背面写上了数字\(b_i\)。最初所有牌都是正面朝上。有\(m\)个机器,每个机器有参数\(x_i,y_i(1\lex_i,y_i\len)\),\(x_i\)可以等于\(y_i\)。每个机器只能启动一次,并且有\(\frac{1}{2}\)的概率将牌\(......
  • AtCoder Beginner Contest 313
    A-ToBeSaikyo#include<bits/stdc++.h>usingnamespacestd;intmain(){ ios::sync_with_stdio(0),cin.tie(0); intn; cin>>n; vector<int>a(n); for(auto&i:a)cin>>i; cout<<max(0,*max_element(a.beg......
  • 「解题报告」AtCoder Beginner Contest 313
    比赛地址:AtCoderBeginnerContest313-AtCoder后记:请正确理解题意后再做题!!!A-ToBeSaikyoA-ToBeSaikyo(atcoder.jp)每个人有一个数值,问第一个人要加多少才能使得自己的数值变成最大的。就这么个破题我还WA了一发//Thecodewaswrittenbyyifan,andyifanis......
  • AtCoder Beginner Contest (ABC) 313 D-E
    Tasks-AtCoderBeginnerContest313PS:当时看到D过的比E多就一直在考虑D,但还没做出来,其实个人感觉E比D简单。 D-OddorEven交互题。有n个数,最多可以询问n次然后要求判断出这n个数的奇偶性。每次可以询问数组里任意k个元素的和是不是奇数一开始想到的是高斯消元,n次总能......