zoukankan      html  css  js  c++  java
  • Gym

    题意:有一个长度为n的01序列,你可以移动k次,每次将一个数移到任意一个位置,求经过操作后区间连续最大的连续0的个数。

    “移动”操作看似情况很复杂,不好讨论,但其实无非就两种情况:

    一、移动的是1:显然最优的策略是将1移动到最边上(相当于“移走”),目的是将两段连续的0合并。

    二、移动的是0:最优策略是将小堆中的0移动到大堆里,目的是增加大堆中0的个数。

    这样一来,情况就简单多了,问题转化成了求“将一段连续区间中的0合并,然后剩下的操作次数用于把其他地方的0引进来”的最优解,即求$min(maxleft{sumlimits_{ileqslant j,cnt0(i,j)leqslant k}(cnt0(i,j)+(k-cnt1(i,j))) ight},cnt0(1,n))$,前缀和+单调队列搞一搞就行了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e6+10;
     5 char s[N];
     6 int n,m,k,a[N],b[N],hd,tl;
     7 struct P {int x,y;} q[N];
     8 int main() {
     9     scanf("%s",s+1),n=strlen(s+1);
    10     for(int i=1; i<=n; ++i)a[i]=a[i-1]+(s[i]=='0'),b[i]=b[i-1]+(s[i]=='1');
    11     scanf("%d",&m);
    12     while(m--) {
    13         int ans=0;
    14         scanf("%d",&k);
    15         hd=tl=0;
    16         for(int j=0,i=0; j<=n; ++j) {
    17             for(; i<=j&&b[j]-b[i-1]>k; ++i);
    18             for(; hd<tl&&q[hd].x<i-1; ++hd);
    19             P np= {j,a[j]-b[j]};
    20             for(; hd<tl&&q[tl-1].y>=np.y; --tl);
    21             q[tl++]=np;
    22             ans=max(ans,(a[j]-b[j])+(k-q[hd].y));
    23         }
    24         ans=min(ans,a[n]);
    25         printf("%d
    ",ans);
    26     }
    27     return 0;
    28 }
  • 相关阅读:
    static作用(修饰函数、局部变量、全局变量)(转)
    地弹
    开漏(open drain)和开集(open colletor)
    过冲、振铃,非单调性
    串扰(crosstalk)
    数字通信基本概念
    电源和地
    分布式系统与集总系统
    传输线及其特性阻抗
    MSP430G2553 Launchpad 硬件I2C驱动
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11544470.html
Copyright © 2011-2022 走看看