BZOJ 1122 POI2008 账本BBB 单调队列
2015-06-08 16:41
375 查看
题目大意:给定一个由+1+1和−1-1构成的长度为nn的序列,提供两种操作:
1.将某一位取反,花销为xx
2.将最后一位移动到前一位,花销为yy
要求最终p+sumn=qp+sum_n=q,且p+sumi≥0(1≤i≤n)p+sum_i\geq 0(1\leq i\leq n),求最小花销
枚举最终的序列以哪个点开始,那么从这个点往后的最小前缀和可以用单调队列预处理出来
然后贪心地把左边的−1-1改成+1+1,右边的+1+1改成−1-1直到满足要求即可
1.将某一位取反,花销为xx
2.将最后一位移动到前一位,花销为yy
要求最终p+sumn=qp+sum_n=q,且p+sumi≥0(1≤i≤n)p+sum_i\geq 0(1\leq i\leq n),求最小花销
枚举最终的序列以哪个点开始,那么从这个点往后的最小前缀和可以用单调队列预处理出来
然后贪心地把左边的−1-1改成+1+1,右边的+1+1改成−1-1直到满足要求即可
[code]#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 2002002 using namespace std; int n,p,q; long long x,y,ans=0x7fffffffffffffffll; char s[M]; int sum[M],_min[M]; void Assert(bool flag) { if(flag) return ; printf("%d\n",1/0); exit(0); } int main() { int i; cin>>n>>p>>q>>x>>y; scanf("%s",s+1); for(i=n<<1;i>n;i--) sum[i]=sum[i+1]+(s[i-n]=='-'?-1:1); for(i=n;i;i--) sum[i]=sum[i+1]+(s[i]=='-'?-1:1); static int q[M],r,h; for(i=n<<1;i;i--) { while( r-h>=1 && sum[q[r]]<sum[i] ) q[r--]=0; q[++r]=i; while( q[h+1]-i>n ) q[++h]=0; if(i<=n) _min[i]=sum[i]-sum[q[h+1]]; } Assert( ~ (::q)-p - sum[n+1] & 1 ); int temp=(::q-p)-sum[n+1]>>1; for(i=1;i<=n;i++) { long long cost=(n-i+1)%n*y+abs(temp)*x; _min[i]+=p+max(temp,0)*2; if(_min[i]<0) cost+=(1-_min[i]>>1)*x*2; if(cost<ans) ans=cost; } cout<<ans<<endl; return 0; }
相关文章推荐
- 2、Django中模板的使用
- 至少原则平方多项式曲线拟合和实施
- TCP在三次握手协议和四波(图)
- centos rm文件删除恢复
- Search Bars(一)
- Convert Sorted Array to Binary Search Tree || LeetCode
- IE中的cursor存在的bug
- 机器学习--朴素贝叶斯
- VIM - 配置文件vimrc示例
- Spring MVC过滤器-登录过滤
- protocol buffer
- 事件(Event)
- OpenGL超级宝典第5版&&缓冲区
- FOR XML PATH 解决联接返回结果集各记录问题
- 3SUM
- VS2010中打开VS2013的C#项目的方法
- Stanley-系列三
- AIDL 进程间通信
- Java访问远程服务
- Java中泛型的各种使用