zoukankan      html  css  js  c++  java
  • [bzoj1122]账本

    简化问题:如果没有2操作,答案是多少
    贪心:修改-一定修改最前面的,修改+一定修改最后面的,正确性显然
    而通过1操作,要完成两步:1.让最终结果为q;2.让前缀和非负,通过贪心可以获得最小值
    (具体来说,假设初始有nq个+,np个-,第一步操作后前缀最小值为k,那么答案为$(|p+nq-np-q|/2+max(p-k,0))x$)
    那么枚举2操作的次数,考虑此时的答案,即要快速维护之前的贪心过程
    前半部分的代价没有改变,相当于要快速维护前缀最小值
    这个东西显然可以用优先队列来维护,复杂度$o(n)$
    (同时要注意可能第二步的操作可以用第一步来实现(表达不清淅))

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2000005
     4 int n,p,qq,x,y,l,r,s2,a[N],sum[N],q[N];
     5 long long ans,s1;
     6 char s[N];
     7 int main(){
     8     scanf("%d%d%d%d%d%s",&n,&p,&qq,&x,&y,s);
     9     for(int i=1;i<=n;i++)
    10         if (s[i-1]=='+')a[i]=a[i+n]=1;
    11         else a[i]=a[i+n]=-1;
    12     ans=1LL*n*x;
    13     for(int i=1;i<2*n;i++){
    14         while ((l<r)&&(q[l]<=i-n))l++;
    15         sum[i]=sum[i-1]+a[i];
    16         while ((l<r)&&(sum[i]<=sum[q[r-1]]))r--;
    17         q[r++]=i;
    18         if (i>=n){
    19             if (i==n)s1=0;
    20             else s1=n*2-i;
    21             s1*=y;
    22             s2=(1-p-sum[q[l]]+sum[i-n])/2;
    23             if (s2<=0)ans=min(ans,s1+abs(p-qq+sum[n])/2LL*x);
    24             else ans=min(ans,s1+1LL*s2*x+abs(p-qq+sum[n]+s2*2)/2LL*x);
    25         }
    26     }
    27     printf("%lld",ans);
    28 }
    View Code
  • 相关阅读:
    BDD
    linux 删除中文名称乱码的文件
    python代码调用linux命令
    linux 查看内存
    java学习day17--API-注解
    java学习day17--API-单例设计模式
    java学习day17--API-同步锁
    java学习day16--API-多线程创建两种方式
    java学习day16--API-多线程-->进程和线程
    java学习day15--API-Map-->HashMap
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11561873.html
Copyright © 2011-2022 走看看