[bzoj1122]账本
2024-10-12 17:48:03
简化问题:如果没有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 }
最新文章
- Java中的关键字 transient
- db2 常用命令
- jmap
- HTML 5 Web 存储
- 解决file_get_contents无法请求https连接的方法
- VMware Workstation 下进行 桥连接
- c#控制IE浏览器自动点击等事件WebBrowser,mshtml.IHTMLDocument2 .
- 读取iOS通讯录
- Heap:Expedition(POJ 2431)
- git操作技巧(转载)
- hibernate4.0+版本和3.0+版本的区别总结
- Java获取当前日期的前一个月,前一天的时间
- PHP常用表达式用法
- Mybatis迷你版--QueryObjectFactory
- build配置项中maven常用插件
- css繼承
- 分类Category的概念和使用流程
- c#用表达式树实现深拷贝功能
- 【BZOJ】1704: [Usaco2007 Mar]Face The Right Way 自动转身机
- ASP.NET MVC Cookie 身份验证