• [cf573E]Bear and Bowling


    结论:假设$a_{x}=max_{i=1}^{n}a_{i}$,对于任意$1le lle 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 lle ile r,w_{i}=w_{i}+a_{i}$

    2.给定$l,r$和$x$,令$forall lle ile 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(nlog^{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
    ",ans);
    104     return 0;
    105 }
    View Code
  • 相关阅读:
    jquery之empty()与remove()区别
    (四)快速排序
    (三)归并排序
    (二)希尔排序
    (一)冒泡排序、插入排序、选择排序
    四,JVM 自带工具之jvisualvm
    JAVA多线程之Volatiles
    JAVA多线程之线程池的使用
    CountDownLatch与CyclicBarrier的使用与区别
    乐观锁与悲观锁及其实现
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15397483.html
Copyright © 2020-2023  润新知