[POI2014]Salad Bar
题目大意:
一个长度为$n(n\leq10^6)$的字符串,每一位只会是$p$或$j$。你需要取出一个子串$S$(从左到右或从右到左一个一个取出),使得不管是从左往右还是从右往左取,都保证每时每刻已取出的$p$的个数不小于$j$的个数。你需要最大化$|S|$。
思路:
令$p$为$1$,$j$为$-1$。用$sum[i]$表示$1\sim i$的前缀和,则题目所求相当于找到一个最长的区间$[l,r]$,满足$\forall i\in[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\n",ans); 69 return 0; 70 }