The Solution of CF1630D
是我 idea 弱化版 /fn
(以下内容除了 Hint 选自官方 Editorial 帮助理解外,其他均为原创。)
视频讲解
大意
给定长度为
你可以进行无限次操作,每次操作:
- 选择一个
x 和一个区间[l,r] ,其中有x\in B,1\le l\le r\le n 且r-l+1=x 。 - 把所有
i\in [l,r] 的a_i 变成-a_i 。
求操作后
Hint 1
最短的可操作区间长度是多少?
Hint 2
构造长度为
解法
以下我们把「选择区间
如果我们有
- 依次进行
q(k+1,k+x),q(k+x-y+1,k+x) ,即可实现,其中k 是我们要实现的长度为x-y 的区间的左端点。 - 依次进行
q(k-x+1,k),q(k-x+1,k-x+y) ,即可实现,其中k 是我们要实现的长度为x-y 的区间的右端点。
于是我们可以直接把
令
于是问题转化为:
进行任意次
p(g) ,最大化\sum a_i 。
考虑「Hint 2」的定义,
我们定义
所以只有使所有
于是可以考虑 dp。
设
考虑答案,显然是
时间复杂度
核心代码
for(int i = 0 ; i < m ; i++)
g = gcd(g, b[i]);
for(int i = 0 ; i < g ; i++)
dp[i][0] = 0, dp[i][1] = -3e9;
for(int i = 0 ; i < n ; i++){
ll x1 = dp[i % g][0], x2 = dp[i % g][1];
dp[i % g][0] = max(x1 + a[i], x2 - a[i]);
dp[i % g][1] = max(x2 + a[i], x1 - a[i]);
}
sum1 = sum2 = 0;
for(int i = 0 ; i < g ; i++)
sum1 += dp[i][0], sum2 += dp[i][1];
printf("%lld\n", max(sum1, sum2));
完整版本(