• bzoj 1122 [POI2008]账本BBB 模拟贪心,单调队列


     [POI2008]账本BBB

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 524  Solved: 251
    [Submit][Status][Discuss]

    Description

    一个长度为n的记账单,+表示存¥1,-表示取¥1。现在发现记账单有问题。一开始本来已经存了¥p,并且知道最后账户上还有¥q。你要把记账单修改正确,使得 1:账户永远不会出现负数; 2:最后账户上还有¥q。你有2种操作: 1:对某一位取反,耗时x; 2:把最后一位移到第一位,耗时y。

    Input

    The first line contains 5 integers n, p, q, x and y (1  n  1000000, 0  p;q  1000000, 1  x;y  1000), separated by single spaces and denoting respectively: the number of transactions done by Byteasar, initial and final account balance and the number of seconds needed to perform a single turn (change of sign) and move of transaction to the beginning. The second line contains a sequence of n signs (each a plus or a minus), with no spaces in-between. 1 ≤ n ≤ 1000000, 0 ≤ p ,q ≤ 1000000, 1 ≤x,y ≤ 1000)

    Output

    修改消耗的时间

    Sample Input

    9 2 3 2 1
    ---++++++

    Sample Output

    3

    HINT

    若p+序列和≠q,可以发现取反操作数量是确定的
    尽量在前面做加法,后面做减法

    旋转操作,暴力想法是把最后一位提前,就相当于连成一个环,在环上求值

    所以在环上枚举起点

    暴力走一遍环单纯是为了解决非负的问题

    在环上用单调队列求一遍最小值,再枚举起点做无旋转的修改

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<queue>
     6 
     7 #define N 1000007
     8 #define ll long long
     9 inline ll read()
    10 {
    11     ll x=0,f=1;char ch=getchar();
    12     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    13     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 
    17 ll n,p,q,x,y;
    18 int que[N<<1],seq[N<<1],mn[N];
    19 char ch[N];
    20 
    21 inline ll max(ll a,ll b)
    22 {
    23     if (a>b) return a;
    24     else return b;
    25 }
    26 inline ll min(ll a,ll b)
    27 {
    28     if (a>b) return b;
    29     else return a;
    30 }
    31 inline ll abs(ll a)
    32 {
    33     if (a>0) return a;
    34     else return -a;
    35 }
    36 int main()
    37 {
    38     n=read(),p=read(),q=read(),x=read(),y=read();
    39     scanf("%s",ch+1);
    40     for (int i=n<<1;i>n;i--)
    41         seq[i]=seq[i+1]+(ch[i-n]=='+'?1:-1);
    42     for (int i=n;i>=1;i--)
    43         seq[i]=seq[i+1]+(ch[i]=='+'?1:-1);
    44     int hd=1,tl=0;
    45     for (int i=n<<1;i>=1;i--)
    46     {
    47         while(hd<=tl&&seq[i]>seq[que[tl]]) tl--;
    48         que[++tl]=i;
    49         while(hd<=tl&&seq[hd]-i>=n) hd++;
    50         if (i<=n) mn[i]=seq[i]-seq[que[hd]];
    51     } 
    52     ll total=seq[n+1],tmp=(q-p-total)/2,ans=1e16,res;
    53     for (int i=0;i<n;i++)
    54     {
    55         res=x*abs(tmp)+y*(ll)i;
    56         if (i==0)
    57         {
    58             mn[1]+=p+max(tmp,0)*2;
    59             if (mn[1]<0) res+=2*x*((1-mn[1])/2);
    60         }
    61         else
    62         {
    63             mn[n-i+1]+=p+max(tmp,0)*2;
    64             if (mn[n-i+1]<0) res+=2*x*((1-mn[n-i+1])/2);
    65         }
    66         ans=min(ans,res);
    67     }
    68     printf("%lld
    ",ans);
    69 }
  • 相关阅读:
    (难)Codeforces Round #406 (Div. 2) C题Berzerk(有向图博弈)解题报告
    jquery清空kindEditor
    处理用户误输入html标签引起的网站布局混乱
    自动闭合所有标签的方法,用于获得textBox等值的时候,标签都是闭合的
    .NET一个页面多个Button按钮事件避免数据验证控件RequiredFieldValidator
    基类包括字段(),但其类型()与控件()的类型不兼容
    关于ajax回调数据类型为Json,如何获得他的值
    如何查找Repeater控件中嵌套的控件
    网站功能
    WIN7系统IIS上发布站点后水印效果失效的解决方法
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8834818.html
Copyright © 2020-2023  润新知