http://codeforces.com/contest/264/problem/C
以前做过 到现在又不会了..qwq
首先我的想法是设\(f[i][0 / 1]\)为\(i\)位是否选择
然后这样转移的话就不知道前一个数是否和这个点颜色相同
其实应该对于颜色设立\(dp\)方程
记\(f[C]\)为color为\(C\)时的是最大的答案
然后转移的话维护一下两种不同颜色的最大值和次大值
复杂度\(\mathcal O(nq)\)
#include <bits/stdc++.h>
#define int long long
#define rint register int
#define fo(i, n) for(rint i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0;char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
const int N = 1e5 + 233;
int n, Q, a, b;
int v[N], c[N], vis[N], pre[N], f[N];
// dp[i] 表示颜色为 i 的最大的答案
inline void U(int &x, int y) {
if(x < y) x = y;
}
inline int cal(int n, int fff) {
return v[n] * (fff ? a : b);
}
main(void) {
read(n); read(Q);
for(int i = 1; i <= n; i ++)
read(v[i]);
for(int i = 1; i <= n; i ++)
read(c[i]);
for(int i = 1; i <= n; i ++) {
if(vis[c[i]]) pre[i] = vis[c[i]];
vis[c[i]] = i;
}
while(Q --) {
read(a); read(b);
memset(f, 168, sizeof f);
int Max = 0, Sec = 0;
int Maxc = 0, Secc = 0;
for(int i = 1; i <= n; i ++) {
int C = c[i], V = v[i];
if(pre[i]) U(f[C], f[C] + V * a);
if(Maxc != C) U(f[C], Max + V * b);
else if(Secc != C) U(f[C], Sec + V * b);
if(f[C] > Max) {
if(Maxc != C)
Sec = Max, Secc = Maxc;
Max = f[C], Maxc = C;
}
else if(f[C] > Sec && C != Maxc) Sec = f[C], Secc = C;
}
cout << max(0ll, *max_element(f + 1, f + N)) << "\n";
}
}