题目
题目描述
给定一个长度为 n n n 的正整数数组 A A A,其中所有数从左至右排成一排。
你需要将 A A A 中的每个数染成红色或蓝色之一,然后按如下方式计算最终得分:
设 C C C 为长度为 n n n 的整数数组,对于 A A A 中的每个数 A i A_i Ai( 1 ≤ i ≤ n 1 \leq i \leq n 1≤i≤n):
- 如果 A i A_i Ai 左侧没有与其同色的数,则令 C i = 0 C_i = 0 Ci=0。
- 否则,记其左侧与其最靠近的同色数为 A j A_j Aj,若 A i = A j A_i = A_j Ai=Aj,则令 C i = A i C_i = A_i Ci=Ai,否则令 C i = 0 C_i = 0 Ci=0。
你的最终得分为 C C C 中所有整数的和,即 ∑ i = 1 n C i \sum \limits_{i=1}^n C_i i=1∑nCi。你需要最大化最终得分,请求出最终得分的最大值。
输入格式
本题有多组测试数据。
输入的第一行包含一个正整数 T T T,表示数据组数。
接下来包含 T T T 组数据,每组数据的格式如下:
第一行包含一个正整数 n n n,表示数组长度。
第二行包含 n n n 个正整数 A 1 , A 2 , … , A n A_1, A_2, \dots, A_n A1,A2,…,An,表示数组 A A A 中的元素。
输出格式
对于每组数据:输出一行包含一个非负整数,表示最终得分的最大可能值。
输入输出样例 #1
输入 #1
3
3
1 2 1
4
1 2 3 4
8
3 5 2 5 1 2 1 4
输出 #1
1
0
8
说明/提示
【样例 1 解释】
对于第一组数据,以下为三种可能的染色方案:
- 将 A 1 , A 2 A_1, A_2 A1,A2 染成红色,将 A 3 A_3 A3 染成蓝色( 1 2 1 \red{1}\red{2}\blue{1} 121),其得分计算方式如下:
- 对于 A 1 A_1 A1,由于其左侧没有红色的数,所以 C 1 = 0 C_1 = 0 C1=0。
- 对于 A 2 A_2 A2,其左侧与其最靠近的红色数为 A 1 A_1 A1。由于 A 1 ≠ A 2 A_1 \neq A_2 A1=A2,所以 C 2 = 0 C_2 = 0 C2=0。
- 对于
A
3
A_3
A3,由于其左侧没有蓝色的数,所以
C
3
=
0
C_3 = 0
C3=0。
该方案最终得分为 C 1 + C 2 + C 3 = 0 C_1 + C_2 + C_3 = 0 C1+C2+C3=0。
- 将 A 1 , A 2 , A 3 A_1, A_2, A_3 A1,A2,A3 全部染成红色( 121 \red{121} 121),其得分计算方式如下:
- 对于 A 1 A_1 A1,由于其左侧没有红色的数,所以 C 1 = 0 C_1 = 0 C1=0。
- 对于 A 2 A_2 A2,其左侧与其最靠近的红色数为 A 1 A_1 A1。由于 A 1 ≠ A 2 A_1 \neq A_2 A1=A2,所以 C 2 = 0 C_2 = 0 C2=0。
- 对于
A
3
A_3
A3,其左侧与其最靠近的红色数为
A
2
A_2
A2。由于
A
2
≠
A
3
A_2 \neq A_3
A2=A3,所以
C
3
=
0
C_3 = 0
C3=0。
该方案最终得分为 C 1 + C 2 + C 3 = 0 C_1 + C_2 + C_3 = 0 C1+C2+C3=0。
- 将 A 1 , A 3 A_1, A_3 A1,A3 染成红色,将 A 2 A_2 A2 染成蓝色( 1 2 1 \red{1}\blue{2}\red{1} 121),其得分计算方式如下:
- 对于 A 1 A_1 A1,由于其左侧没有红色的数,所以 C 1 = 0 C_1 = 0 C1=0。
- 对于 A 2 A_2 A2,由于其左侧没有蓝色的数,所以 C 2 = 0 C_2 = 0 C2=0。
- 对于
A
3
A_3
A3,其左侧与其最靠近的红色数为
A
1
A_1
A1。由于
A
1
=
A
3
A_1 = A_3
A1=A3,所以
C
3
=
A
3
=
1
C_3 = A_3 = 1
C3=A3=1。
该方案最终得分为 C 1 + C 2 + C 3 = 1 C_1 + C_2 + C_3 = 1 C1+C2+C3=1。
可以证明,没有染色方案使得最终得分大于 1 1 1。
对于第二组数据,可以证明,任何染色方案的最终得分都是 0 0 0。
对于第三组数据,一种最优的染色方案为将 A 1 , A 2 , A 4 , A 5 , A 7 A_1, A_2, A_4, A_5, A_7 A1,A2,A4,A5,A7 染为红色,将 A 3 , A 6 , A 8 A_3, A_6, A_8 A3,A6,A8 染为蓝色( 35 2 51 2 1 4 \red{35}\blue{2}\red{51}\blue{2}\red{1}\blue{4} 35251214),其对应 C = [ 0 , 0 , 0 , 5 , 0 , 1 , 2 , 0 ] C = [0, 0, 0, 5, 0, 1, 2, 0] C=[0,0,0,5,0,1,2,0],最终得分为 8 8 8。
【样例 2】
见选手目录下的 color/color2.in 与 color/color2.ans。
【数据范围】
对于所有测试数据,保证: 1 ≤ T ≤ 10 1\leq T\leq 10 1≤T≤10, 2 ≤ n ≤ 2 × 1 0 5 2\leq n\leq 2\times 10^5 2≤n≤2×105, 1 ≤ A i ≤ 1 0 6 1\leq A_i\leq 10^6 1≤Ai≤106。
测试点 | n n n | A i A_i Ai |
---|---|---|
1 ∼ 4 1\sim 4 1∼4 | ≤ 15 \leq 15 ≤15 | ≤ 15 \leq 15 ≤15 |
5 ∼ 7 5\sim 7 5∼7 | ≤ 1 0 2 \leq 10^2 ≤102 | ≤ 1 0 2 \leq 10^2 ≤102 |
8 ∼ 10 8\sim 10 8∼10 | ≤ 2000 \leq 2000 ≤2000 | ≤ 2000 \leq 2000 ≤2000 |
11 , 12 11,12 11,12 | ≤ 2 × 1 0 4 \leq 2\times 10^4 ≤2×104 | ≤ 1 0 6 \leq 10^6 ≤106 |
13 ∼ 15 13\sim 15 13∼15 | ≤ 2 × 1 0 5 \leq 2\times 10^5 ≤2×105 | ≤ 10 \leq 10 ≤10 |
16 ∼ 20 16\sim 20 16∼20 | ≤ 2 × 1 0 5 \leq 2\times 10^5 ≤2×105 | ≤ 1 0 6 \leq 10^6 ≤106 |
解析
我们设
d
p
i
dp_i
dpi 表示到
i
i
i 为止前面数的最大得分,
l
s
t
a
i
lst_{a_i}
lstai表示在这个点前面
a
i
a_i
ai 出现的位置,
s
u
m
i
sum_i
sumi 表示到i为止的最大相邻的价值和
(
(
(具体见代码
)
)
)
那么我们可以得到
d
p
i
=
m
a
x
(
d
p
i
−
1
,
d
p
l
s
t
a
i
+
a
i
+
s
u
m
i
−
1
−
s
u
m
l
s
t
a
i
)
dp_i = max(dp_{i - 1}, dp_{lst _ {a_i}} + a_i + sum_{i - 1} - sum_{lst_{a_i}})
dpi=max(dpi−1,dplstai+ai+sumi−1−sumlstai)
但是,这个是错的
我被卡了半天
- 因为如果出现如下图这种情况,我们没有统计
- 如果出现相邻的两个相同的 a i a_i ai的话,两个 s u m sum sum相减会出现负数,应该为0
1解释:因为我们直接从lst[4]转移,所以我们没有把两对3加进去,但是事实来说是可以加进去的,所以我们的 d p l s t a i dp_{lst _ {a_i}} dplstai因改为 d p l s t a i + 1 dp_{lst _ {a_i} + 1} dplstai+1
2解释:一旦出现相邻的话,我们就会加一个负数,在不相邻情况,一直 a i ≠ a i − 1 a_i \neq a_{i-1} ai=ai−1,所以 s u m i = s u m i − 1 sum_i = sum_{i-1} sumi=sumi−1, 所以我们把 s u m i − 1 sum_{i - 1} sumi−1 改为 s u m i sum_{i } sumi, 我们经过验算,发现此时 s u m i − s u m l s t a i sum_{i} - sum_{lst_{a_i}} sumi−sumlstai正好为 0 0 0
所以最终得到的转移式为: d p i = m a x ( d p i − 1 , d p l s t a i + 1 + a i + s u m i − s u m l s t a i ) dp_i = max(dp_{i - 1}, dp_{lst _ {a_i} + 1} + a_i + sum_{i} - sum_{lst_{a_i}}) dpi=max(dpi−1,dplstai+1+ai+sumi−sumlstai)
所以大功告成, 请见代码
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
namespace langfengya
{
void Main();
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
langfengya::Main();
return 0;
}
namespace langfengya
{
const int N = 2e5 + 10;
int f[N];
int sum[N], a[N];
int t;
int n;
int last[1000010];
void read()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i] * (a[i] == a[i - 1]);
}
}
void solve()
{
cin >> t;
while (t--)
{
read();
memset(last, 0, sizeof(last));
for (int i = 1; i <= n; i++)
{
f[i] = f[i - 1];
if (last[a[i]])
{
f[i] = max(f[i], f[ last[a[i]] + 1] + sum[i] - sum[ last[a[i]] + 1 ] + a[i]);
}
last[a[i]] = i;
}
cout << f[n] << endl;
}
}
void Main()
{
solve();
}
}