終於在nowcoder爆發了的懶惰
阿新 • • 發佈:2018-11-02
題目
這類題目我實在忍不了了
Emma,隨便做個nowcode比賽題吧,我在oj上也沒找到
題意
求\(\sum_{L=1}^{n}\sum_{R=i}^{n}a[k](L<=k<=R)\),使得和最大
就是求所有子串的最大值之和
思路
我們用一個tot維護 \(\sum_{1}^{i}\)的字首最大值
\(tot<=>\sum_{1}^{i}\)的字首最大值$
我們容易發現,陣列中的值都是單調遞增的
然後我們就維護這個陣列,使他每次轉移的時候更新個答案ans就ok了
\(ans<=>前i個數的答案\)
維護的時候用單調棧就ok了
一開始我理解為單調佇列,其實他是個單調棧
他只有一個指標,也就是棧頂在移動
你也可以想象成左邊不動的單調佇列
舉個例子(這裡我們只求子串最大值)
1 3 2
佇列為空,1進棧 tot[1]=1,ans[1]=1
1彈棧,3進棧 tot[2]=2*3, ans[2]=ans[1]+tot[2]=7;
2進棧 tot[3]=tot[2]+2=8, ans[3]=ans[2]+tot[3]=15;
(這裡包含了長度為1的子串)
需要注意的地方
這裡5w*5w是炸longlong的
所以
tot+=a[i]*(q[t]-q[t-1]);
這句話後半句是已經炸longlong的,炸longlong無處不在,還是隨手開longlong的穩啊
程式碼
#include <iostream> #include <cstdio> #define ll long long #define FOR(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int maxn=1e5+7; int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=(x<<1)+(x<<3)+s-'0'; return x*f; } ll n,a[maxn],q[maxn]; ll solve() { ll ans=0,tot=0,t=0; FOR(i,1,n) { while(t>=1 && a[i]>=a[q[t]]) tot-=a[q[t]]*(q[t]-q[t-1]),t--; q[++t]=i; tot+=a[i]*(q[t]-q[t-1]); ans+=tot; } return ans; } int main() { int T=read(); FOR(kkk,1,T) { n=read(); FOR(i,1,n) a[i]=read(); ll ans1=solve(); FOR(i,1,n) a[i]=-a[i]; ll ans2=solve(); cout<<ans1+ans2<<"\n"; } return 0; }