10
14
2015
0

3521: [Poi2014]Salad Bar

3521: [Poi2014]Salad Bar

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 226  Solved: 104
[Submit][Status][Discuss]

Description

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

 

Input


第一行一个数n,第二行一个长度n的字符串。

 

Output

S的最大长度。

 

Sample Input

6
jpjppj

 

Sample Output

4

HINT

 



【样例解释】

取pjpp这个串。




【数据范围】

n≤1000000


 

 

Source

   把j看成-1,p看成1。。然后询问的串就可以改为l到r中r的前缀和最大且l-1的前缀和最小。。

   然后我们用单调队列求出每一个点向前第一个比他大的点的位置。。然后枚举r用线段树查询以他为结尾的区间最靠前的最小值的位置。。然后更新答案。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000010;
struct Tree{int l,r,Min;} tree[N<<2]; 
char s[N];
int n,a[N],ans,pos,val,h,t,q[N],l[N];
int read(){
	int x = 0,f = 1,c = getchar();
	while (c<'0' || c>'9') {if (c=='-') f = -1;c = getchar();}
	while (c>='0' && c<='9') x = x*10+c-'0',c = getchar();
	return x*f;
}
void Build(int pos,int l,int r){
	tree[pos].l = l;tree[pos].r = r;
	if (l==r) {tree[pos].Min = a[l];return;}
	int mid = (l+r)>>1;
	Build(pos<<1,l,mid);Build(pos<<1|1,mid+1,r);
	tree[pos].Min = min(tree[pos<<1].Min,tree[pos<<1|1].Min);
}
int QueryMin(int pos,int l,int r){
	if (tree[pos].l==l && tree[pos].r==r) return tree[pos].Min;
	int mid = (tree[pos].l+tree[pos].r)>>1;
	if (r<=mid) return QueryMin(pos<<1,l,r);
	else if (l>mid) return QueryMin(pos<<1|1,l,r);
	else return min(QueryMin(pos<<1,l,mid),QueryMin(pos<<1|1,mid+1,r));
}
int find(int pos){
	if (tree[pos].l==tree[pos].r) return tree[pos].l;
	if (tree[pos<<1].Min==val) find(pos<<1);
	else find(pos<<1|1);
}
int Querypos(int pos,int l,int r){
	if (tree[pos].l==l && tree[pos].r==r){
		if (tree[pos].Min==val) return find(pos);
		else return 1e9;
	}
	int mid = (tree[pos].l+tree[pos].r)>>1;
	if (r<=mid) return Querypos(pos<<1,l,r);
	else if (l>mid) return Querypos(pos<<1|1,l,r);
	else return min(Querypos(pos<<1,l,mid),Querypos(pos<<1|1,mid+1,r));
}
int main(){
	n = read();
	scanf("%s",s+1);
	for (int i=1;i<=n;i++)
		if (s[i]=='j') a[i] = a[i-1]-1;else a[i] = a[i-1]+1;
	Build(1,0,n);
	a[0] = 1e9;
	q[0] = 0;t = 0;
	for (int i=1;i<=n;i++){
		while (t && a[q[t]]<=a[i]) t--;
		l[i] = q[t];q[++t] = i;
	}
	for (int i=1;i<=n;i++){
		val = QueryMin(1,l[i],i);
		pos = Querypos(1,l[i],i);
		if (i-pos>ans) ans = i-pos;
	}
	printf("%d",ans);
}
Category: BZOJ题解 | Tags: | Read Count: 587

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com