1 /*
2 Source : wannafly21
3 Problem :给出一个长度为n的序列,每个位置有一个值和一个权重,可以把两个位置值相同的一段连起来作为一个操作,得分为对应的权重之和,每个位置只能连一次,
4 求最终最大的和。
5 Solution :dp[i] = dp[j] + sum(i,j) , a[i]==a[j]
6 优化: 假设j为i前面一个相同的值,dp[j] 对应的最优位置在x
7 那么dp[i]对应对应的最优值的位置在j 或者 x; 位置j是可能的,其余的位置的结果都必然不优于x
8 由dp[j]的结果可得,对于任意的一个y a[y]==a[x] 有 dp[x]+sum(x,j) >= dp[y]+sum(y,j)
9 相应的就有 dp[x] + sum(x, i) = dp[x] + sum(x, j) + sum(j, i) >= dp[y] + sum(y, j) + sum(j, i) = dp[y] + sum(y, i)
10 Date :2018-08-10-11.50
11 */
12
13 #include <bits/stdc++.h>
14 using namespace std;
15
16 typedef long long LL;
17 const int MAXN = 300005;
18 const LL MOD7 = 1e9+7;
19 int n;
20
21 LL a[MAXN];
22 LL g[MAXN];
23 LL dp[MAXN];
24 LL sum[MAXN];
25 int pos[MAXN];
26 int pre[MAXN];
27 map<LL, int> mp;
28
29 void work()
30 {
31 LL ans=0;
32 memset(dp,0,sizeof(dp));
33 memset(pos,0,sizeof(pos));
34 mp.clear();
35 memset(pre,0,sizeof(pre));
36 for (int i=1;i<=n;++i)
37 {
38 if (mp.find(a[i])!=mp.end())
39 {
40 pre[i]=mp[a[i]];
41 }
42 mp[a[i]]=i;
43 sum[i] = sum[i-1] + g[i];
44 }
45 for (int i=1;i<=n;++i)
46 {
47 if (pre[i]!=0)
48 {
49 dp[i] = dp[pre[i]-1] + sum[i] - sum[pre[i]-1];
50 pos[i]=pre[i];
51 if (pre[pre[i]]!=0 && dp[pre[pre[i]]-1] + sum[i]-sum[pre[pre[i]]-1] > dp[i])
52 {
53 dp[i] = dp[pre[pre[i]]-1] + sum[i]-sum[pre[pre[i]]-1];
54 pre[i] = pre[pre[i]];
55 }
56 }
57 ans=max(ans, dp[i]);
58 }
59 printf("%lld\n",ans);
60 }
61
62 int main()
63 {
64 #ifndef ONLINE_JUDGE
65 freopen("test.txt","r",stdin);
66 #endif // ONLINE_JUDGE
67 int Case;
68 // scanf("%d",&Case);
69 while (scanf("%d",&n)!=-1)
70 {
71 for (int i=1;i<=n;++i)
72 {
73 scanf("%lld",&a[i]);
74 }
75 for (int i=1;i<=n;++i)
76 {
77 scanf("%lld",&g[i]);
78 }
79 work();
80 }
81 return 0;
82 }
83
84 //7
85 //1 2 1 2 3 2 3
86 //1 4 3 4 3 4 5
87 //15
88 //1 2 1 2 1 2 1 2 1 2 1 2 1 2 1
89 //5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
90 //5
91 //1 2 1 2 1
92 //5 5 5 5 5
93 //
94 //
95 //
96 //
97 //out:
98 //23
99 //75
100 //25