卡了2天,说多了都是泪。
/*
该点的最大值的可以由前面某个点加上相应的值得到。
而前面的点可以分析为以下的条件
1、前面的这个点与该点颜色相同。
2、这个点与这个点颜色不同。
3、前面没有点。
现在分析:
由于1、3两个条件已经是o(1)的时间,所以不需要优化。
主要的时间出在于2的时间,2需要遍历。
假设2里面有n个条件需要判断,其实归结起来,我们只需要判断两个情况
1、这个点的颜色与该点相同
2、这个点的颜色与该点不同。
而且假如不同的话,加上的差值都是一样的,所以我们应该选择一个积累了最大的与该点颜色不同的点加上该差值,那么这个点的值就是达到最大。
这个是由于a,b两个量决定的,所以我们应该在该点当中选择一个最大的即可。
所以优化的方法便是保留两个值,一个是最大,一个是最小。这样就能够保证取到一种颜色不同的最大值
假如保留一个的话可能会有一种情况,即该点的颜色与最大的颜色相同,这样的话便少考虑了一种情况,显然这是不可行的。
dp[i]表示的是i颜色迄今为止所能够达到的最大的值
关于dp的状态量表示的想法:dp[i],对于i的选取一般都选择位置,
但是对于数据量大的时候,我们不妨考虑已知的其他量,然后去推相应的状态方程,假如不行的话,再想相应的优化方法,不失为一个好的决策。
在考虑一点如何转换的时候,不妨考虑该点的转换方向
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long dp[100005];
int c[100005];
long long v[100005];
int id1, id2;
const long long inf = 0x7ffffffffffffff;
int main()
{
int n, m;
while (cin >> n >> m)
{
for (int i = 1; i <= n; i++)
cin >> v[i];
for (int i = 1; i <= n; i++)
scanf("%d", &c[i]);
long long a, b;
for (int i = 0; i < m; i++)
{
long long sum=0, ans;
cin >> a >> b;
id1 = 0;
id2 = 0;
for (int j = 0; j <= n; j++)
dp[j] = -inf;
for (int j = 1; j <= n; j++)
{
int cc = c[j];
ans = max(dp[cc]+a*v[j],b*v[j]);
if (cc != id1)
ans = max(ans, dp[id1] + b*v[j]);
else
ans = max(ans, dp[id2] + b*v[j]);
if (ans > dp[id1])
{
if (id1 != cc)
{
id2 = id1;
id1 = cc;
}
else
id1 = cc;
}
else
if (ans > dp[id2] && cc != id1)
id2 = cc;
dp[cc] = max(dp[cc],ans);
sum = max(ans, sum);
}
cout << sum << endl;
}
}
}
时间: 2024-10-08 02:15:40