zoukankan      html  css  js  c++  java
  • [POI2014]Salad Bar

    题目大意:
      一个长度为$n(nleq10^6)$的字符串,每一位只会是$p$或$j$。你需要取出一个子串$S$(从左到右或从右到左一个一个取出),使得不管是从左往右还是从右往左取,都保证每时每刻已取出的$p$的个数不小于$j$的个数。你需要最大化$|S|$。

    思路:
      令$p$为$1$,$j$为$-1$。用$sum[i]$表示$1sim i$的前缀和,则题目所求相当于找到一个最长的区间$[l,r]$,满足$forall iin[l,r],sum[l-1]le sum[i]le sum[r]$。
      这也就意味着对于一个满足条件的区间$[l,r]$,$sum[l-1]$为最小值,$sum[r]$为最大值。
      预处理每一个位置$i$能扩展到的最左端点$left[i]$和最右端点$right[i]$。答案相当于找到一个区间$[l,r]$使得$left[r]le l,right[l]ge r$。将点按照$right[i]$排序,枚举对应的$i$作为$l$。用树状数组在每个$left[i]$对应的位置上维护最大的$i$。右端点$r$就是当前加入线段树且$left[i]le l$的点中,对应的$i$的最大值。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<climits>
     4 #include<algorithm>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 inline char getalpha() {
    13     register char ch;
    14     while(!isalpha(ch=getchar()));
    15     return ch;
    16 }
    17 const int N=1e6+1;
    18 int n,a[N],pos[N*2],left[N],right[N],seq[N];
    19 inline bool cmp(const int &a,const int &b) {
    20     return right[a]<right[b];
    21 }
    22 class FenwickTree {
    23     private:
    24         int val[N];
    25         int lowbit(const int &x) const {
    26             return x&-x;
    27         }
    28     public:
    29         void modify(int p,const int &x) {
    30             for(;p<=n;p+=lowbit(p)) {
    31                 val[p]=std::max(val[p],x);
    32             }
    33         }
    34         int query(int p) const {
    35             int ret=0;
    36             for(;p;p-=lowbit(p)) {
    37                 ret=std::max(ret,val[p]);
    38             }
    39             return ret;
    40         }
    41 };
    42 FenwickTree t;
    43 int main() {
    44     n=getint();
    45     for(register int i=1;i<=n;i++) {
    46         seq[i]=i;
    47         a[i]=getalpha()=='p'?1:-1;
    48     }
    49     std::fill(&pos[0],&pos[N*2],-1);
    50     for(register int i=1,sum=a[1];i<=n;sum+=a[++i]) {
    51         left[i]=pos[sum+N+1]+2;
    52         pos[sum+N]=i;
    53     }
    54     std::fill(&pos[0],&pos[N*2],n+2);
    55     for(register int i=n,sum=a[n];i>=1;sum+=a[--i]) {
    56         right[i]=pos[sum+N+1]-2;
    57         pos[sum+N]=i;
    58     }
    59     int ans=0;
    60     std::sort(&seq[1],&seq[n]+1,cmp);
    61     for(register int i=1,j=1;i<=n;i++) {
    62         const int l=seq[i];
    63         if(a[l]==-1) continue;
    64         for(;j<=right[l];j++) t.modify(left[j],j);
    65         const int r=t.query(l);
    66         ans=std::max(ans,r-l+1);
    67     }
    68     printf("%d
    ",ans);
    69     return 0;
    70 }
  • 相关阅读:
    为EasySharding.EFCore提供Dapper相关查询扩展
    古典音乐作品编号标记解读
    乐理基础
    音乐指挥家
    2021年,年终总结
    有关Android launchMode 在APP(task)之间的应用——扔物线视频
    Springboot Jpa 有关多数据源的问题
    Python运算符及优先级
    高中信息技术(Python)重难点4:切片
    高中信息技术(Python)必修1 数据与计算 出现的模块和函数
  • 原文地址:https://www.cnblogs.com/skylee03/p/8651419.html
Copyright © 2011-2022 走看看