【極值問題】【CF33C】 Wonderful Randomized Sum
阿新 • • 發佈:2018-10-31
Description
給你一個數列\(A\),你可以選擇任意一個字首和任意一個字尾,字首字尾可重合。給他們乘\(-1\)。求最大能獲得的序列和。
Input
第一行是一個數\(n\)代表數列長度
第二行\(n\)個數字,代表序列的元素
Output
一個數字代表答案
Hint
\(1~\leq~n~\leq~10^5\)
Solution
發現重合的部分相當於沒有修改。於是不妨設前後綴沒有重合。
設修改的原序列字首和為\(A\),字尾和為\(B\),未修改的部分為\(C\),序列和為\(S\),則有\(A+B+C=S\)。
題目要求最大化\(-(A+B)+C\)
於是要最大化\(2C-S\)。發現\(S\)是一個不變數,於是要最大化\(C\)。即求一個最大欄位和。顯然可以DP求解。於是本題可以解決了。
Code
#include<cstdio> #define rg register #define ci const int #define cl const long long typedef long long int ll; template <typename T> inline void qr(T &x) { rg char ch=getchar(),lst=' '; while((ch > '9') || (ch < '0')) lst=ch,ch=getchar(); while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(lst == '-') x=-x; } namespace IO { char buf[120]; } template <typename T> inline void qw(T x,const char aft,const bool pt) { if(x < 0) {x=-x,putchar('-');} rg int top=0; do {IO::buf[++top]=x%10+'0';} while(x/=10); while(top) putchar(IO::buf[top--]); if(pt) putchar(aft); } template <typename T> inline T mmax(const T a,const T b) {return a > b ? a : b;} template <typename T> inline T mmin(const T a,const T b) {return a < b ? a : b;} template <typename T> inline T mabs(const T a) {return a < 0 ? -a : a;} template <typename T> inline void mswap(T &_a,T &_b) { T _temp=_a;_a=_b;_b=_temp; } const int maxn = 100010; int n,ans,sum; int MU[maxn],frog[maxn]; int main() { qr(n); for(rg int i=1;i<=n;++i) qr(MU[i]); for(rg int i=1;i<=n;++i) { frog[i]=mmax(frog[i],frog[i-1]+MU[i]); ans=mmax(ans,frog[i]); sum+=MU[i]; } qw((ans<<1)-sum,'\n',true); return 0; }
Summary
遇到最大化一個值的題目,可以通過數學推導變成單變數極值問題,然後DP或者數學求解。