dp codeforces 264C

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";
  }
}

猜你喜欢

转载自www.cnblogs.com/foreverpiano/p/9287154.html