[cf573E]Bear and Bowling
结论:假设$a_{x}=\max_{i=1}^{n}a_{i}$,对于任意$1\le l\le n$,存在长度为$l$且价值最大的子序列包含$x$
若不存在,任取一个长度为$l$且价值最大的子序列,将其中与$a_{x}$相邻的一项改为$a_{x}$即可
由此,不妨先选择$a_{x}$,并将$x$之前的元素加上$a_{x}$、$x$之后的元素加上自身,进而即变为子问题,重复此过程即可得到任意长度价值最大的子序列,显然其中最大值也即答案
提取这个问题的模型,即维护$\{a_{i}\}$和$\{w_{i}=k_{i}a_{i}+(s_{i}+a_{i})\}$,并支持:
1.给定$l$和$r$,令$\forall l\le i\le r,w_{i}=w_{i}+a_{i}$
2.给定$l,r$和$x$,令$\forall l\le i\le r,w_{i}=w_{i}+x$
3.查询$\max_{i=1}^{n}w_{i}$
操作1和操作3的实现可以参考[CF1178G],同时操作2可以快速维护该节点上信息,那么直接打懒标记即可,势能影响同样至多为$o(\log^{3}n)$
类似地,也可以支持$a_{i}$区间加和$a_{i},w_{i}$同时区间乘(相同的数),另外当乘上负数时可能还需要维护一个区间最小值并将两者交换(这里的$a_{i}$即上面那题的$k_{i}$)
最终,总复杂度为$o(n\log^{2}n+m_{1}\log^{3}n+m_{2}\log n+m_{3}\log^{3}n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define ll long long 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 vector<int>v[N]; 9 int n,x,a[N]; 10 ll sum,ans; 11 struct Seg{ 12 int tag_x[N<<2],mn[N<<2]; 13 ll tag_w[N<<2]; 14 struct Line{ 15 int k; 16 ll b; 17 }f[N<<2]; 18 double get_point(Line x,Line y){ 19 if (x.k==y.k)return 0x3f3f3f3f; 20 return -1.0*(x.b-y.b)/(x.k-y.k); 21 } 22 void upd_x(int k,int x){ 23 tag_x[k]+=x,mn[k]-=x; 24 f[k].b+=(ll)x*f[k].k; 25 } 26 void upd_w(int k,ll x){ 27 tag_w[k]+=x,f[k].b+=x; 28 } 29 void up(int k){ 30 double s=get_point(f[L],f[R]); 31 if (s<0)s=0x3f3f3f3f; 32 s=min(s,(double)0x3f3f3f3f); 33 mn[k]=min(min(mn[L],mn[R]),(int)floor(s)); 34 if (f[L].b>f[R].b)f[k]=f[L]; 35 else f[k]=f[R]; 36 } 37 void down(int k){ 38 upd_x(L,tag_x[k]),upd_x(R,tag_x[k]); 39 upd_w(L,tag_w[k]),upd_w(R,tag_w[k]); 40 tag_x[k]=tag_w[k]=0; 41 } 42 void build(int k,int l,int r){ 43 tag_x[k]=tag_w[k]=0; 44 if (l==r){ 45 mn[k]=0x3f3f3f3f; 46 return; 47 } 48 build(L,l,mid); 49 build(R,mid+1,r); 50 up(k); 51 } 52 void update(int k,int l,int r,int x,Line y){ 53 if (l==r){ 54 f[k]=y; 55 return; 56 } 57 down(k); 58 if (x<=mid)update(L,l,mid,x,y); 59 else update(R,mid+1,r,x,y); 60 up(k); 61 } 62 void update_x(int k,int l,int r,int x,int y,int z){ 63 if ((l>y)||(x>r))return; 64 if ((x<=l)&&(r<=y)&&(mn[k]>=z)){ 65 upd_x(k,z); 66 return; 67 } 68 down(k); 69 update_x(L,l,mid,x,y,z); 70 update_x(R,mid+1,r,x,y,z); 71 up(k); 72 } 73 void update_w(int k,int l,int r,int x,int y,int z){ 74 if ((l>y)||(x>r))return; 75 if ((x<=l)&&(r<=y)){ 76 upd_w(k,z); 77 return; 78 } 79 down(k); 80 update_w(L,l,mid,x,y,z); 81 update_w(R,mid+1,r,x,y,z); 82 up(k); 83 } 84 int query(int k,int l,int r){ 85 if (l==r)return l; 86 down(k); 87 if ((f[k].k==f[L].k)&&(f[k].b==f[L].b))return query(L,l,mid); 88 return query(R,mid+1,r); 89 } 90 }T; 91 int main(){ 92 scanf("%d",&n); 93 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 94 T.build(1,1,n); 95 for(int i=1;i<=n;i++)T.update(1,1,n,i,Seg::Line{a[i],a[i]}); 96 for(int i=1;i<=n;i++){ 97 sum+=T.f[1].b,ans=max(ans,sum); 98 int x=T.query(1,1,n); 99 T.update(1,1,n,x,Seg::Line{0,(ll)-1e18}); 100 T.update_x(1,1,n,x+1,n,1); 101 T.update_w(1,1,n,1,x-1,a[x]); 102 } 103 printf("%lld\n",ans); 104 return 0; 105 }