MYF

Codeforces 264C Choosing Balls

题目链接

codeforces 264C

解题方法:DP

题目分析

题目大意

n个求q次查询,下面的两行分别为价值v[]和颜色c[],然后跟随q组a,b。问何时这个序列的总价值最大。

解析

如果对位置进行dp,那么10^5的二维数组开不了不是对位置进行dp,所以采用对颜色进行DP。
详见:大犇解析

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1)
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#define eps 1e-8
#define INF 1e18
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long ll;
using namespace std;
#define maxn 100005
ll c[100005],v[100005];
ll dp[100005];
int main(){
int n,q;
ll v1,v2,v3,v4;
cin>>n>>q;
for (int i=1; i<=n; i++) {
cin>>v[i];
}
for (int i=1; i<=n; i++) {
cin>>c[i];
}
int a,b;
while (q--) {
cin>>a>>b;
ll mx=-INF,mmx=-INF,ans=0;
int pos=0,ppos=0;
for (int i=0; i<maxn; i++) {
dp[i]=-INF;
}

for (int i=1; i<=n; i++) {
//从当前点开始 v1=b*v[i]
v1=v[i]*b;

//与前一个同色 v3=dp[c[i]]+a*v[i]
v2=dp[c[i]]+a*v[i];

//与前一个异色 v3=max(dp[x],x!=c[i])+v[i]*b
if (c[i]==c[pos]) {
v3=mmx+v[i]*b;
}
else{
v3=mx+v[i]*b;
}

//不更新 dp[c[i]]
v4=dp[c[i]];

dp[c[i]]=max(max(v1, v2), max(v3, v4));

if (dp[c[i]]>mx) {
//维护最大值
if (c[i]==c[pos]) {
pos=i;
mx=dp[c[i]];
}
else{
ppos=pos;
mmx=mx;
pos=i;
mx=dp[c[i]];
}
ans=max(ans, mx);
}
else if (dp[c[i]]>mmx){
//维护次大值
if (c[i]!=c[pos]) {
ppos=i;
mmx=dp[c[i]];
}
}
}
cout<<ans<<endl;
}
}