题意:
有一个公式: a1-a2-a3-a4-a5......-an
q次修改,每次修改一个位置上的数。
输出每次修改完以后,对于这个式子最多加两个括号后的最大值
n<=2000,q<=2000
题解:
每次修改完以后,用动态规划的方法,O(n)的复杂度求最优解。
用dp[i][j][k],表示当前在第i位,还有j个括号没有用,前面有k个有效的前括号的最优值。
代码如下:
// BEGIN CUT HERE // END CUT HERE #line 4 "SuccessiveSubtraction2.cpp" #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <ctime> #include <iostream> #include <algorithm> #include <vector> #include <map> #include <set> #include <string> #include <sstream> #define OUT(x) cout << #x << ": " << (x) << endl #define SZ(x) ((int)x.size()) #define FOR(i, n) for (int i = 0; i < (n); ++i) #define inff 0x3fffffff using namespace std; typedef long long LL; int dp[2100][3][3]; int val[2100]; int n; int solve() { int i,j,k; for(i=0;i<n;i++) { for(j=0;j<=2;j++) { for(k=0;k<=2;k++) dp[i][j][k]=-inff; } } dp[0][2][0]=val[0]; for(i=1;i<n;i++) { for(j=0;j<=2;j++) { dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][0]-val[i]); if(j<2) dp[i][j][0]=max(dp[i][j][0],dp[i-1][j+1][1]-val[i]); if(j==0) dp[i][j][0]=max(dp[i][j][0],dp[i-1][2][2]-val[i]); if(j>0) { dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][1]+val[i]); dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][0]-val[i]); if(j==1) dp[i][j][1]=max(dp[i][j][1],dp[i-1][2][2]+val[i]); } if(j==2) { dp[i][j][2]=max(dp[i][j][2],dp[i-1][j][2]-val[i]); dp[i][j][2]=max(dp[i][j][2],dp[i-1][j][1]+val[i]); dp[i][j][2]=max(dp[i][j][2],dp[i-1][j][0]-val[i]); } } } int re=max(dp[n-1][2][0],dp[n-1][1][0]); re=max(re,dp[n-1][0][0]); re=max(re,dp[n-1][1][1]); re=max(re,dp[n-1][2][1]); re=max(re,dp[n-1][2][2]); return re; } class SuccessiveSubtraction2 { public: vector <int> calc(vector <int> a, vector <int> p, vector <int> v) { int i; n=a.size(); vector<int>ans; for(i=0;i<n;i++) { val[i]=a[i]; } int lp=p.size(); for(i=0;i<lp;i++) { val[p[i]]=v[i]; ans.push_back(solve()); } return ans; }