BZOJ3521: [Poi2014]Salad Bar

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3521

题解:我们考虑把p当作1,j当作-1,然后a[i]表示前缀和。

          画到网格图上,我们很容易观察出,[l,r]满足题中的条件当且仅当 a[l-1]是a[l...r]的最小值,而a[r]是a[l...r]的最大值。

          那这样就很简单了,我们先用单调栈求出l[i],r[i],分别表示 a[i]作为最大值最远拓展到l[i],作为最小值最远拓展到r[i]。

          然后我们可以枚举区间的左端点,查询i-r[i]之间l[x]<=i的。这一步我们可以串个链表,r[x]<=i的时候就把它添入答案候选,然后查询区间最值。

          线段树即可。

代码:

  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 1000000+5
 26 
 27 #define maxm 200000+5
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 44 
 45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
 46 
 47 #define mod 1000000007
 48 #define mid ((l+r)>>1)
 49 #define lch k<<1,l,mid
 50 #define rch k<<1|1,mid+1,r
 51 
 52 using namespace std;
 53 
 54 inline int read()
 55 
 56 {
 57 
 58     int x=0,f=1;char ch=getchar();
 59 
 60     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 61 
 62     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 63 
 64     return x*f;
 65 
 66 }
 67 int n,tot,head[maxn],a[maxn],l[maxn],r[maxn],sta[maxn];
 68 struct seg{int mx;}t[4*maxn];
 69 struct edge{int go,next;}e[maxn];
 70 inline void add(int x,int y)
 71 {
 72     e[++tot]=(edge){y,head[x]};head[x]=tot;
 73 }
 74 inline void pushup(int k)
 75 {
 76     t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
 77 }
 78 inline void change(int k,int l,int r,int x)
 79 {
 80     if(l==r){t[k].mx=l;return;}
 81     if(x<=mid)change(lch,x);else change(rch,x);
 82     pushup(k);
 83 }
 84 inline int query(int k,int l,int r,int x,int y)
 85 {
 86     if(l==x&&r==y)return t[k].mx;
 87     if(y<=mid)return query(lch,x,y);
 88     else if(x>mid)return query(rch,x,y);
 89     else return max(query(lch,x,mid),query(rch,mid+1,y));
 90 }
 91 
 92 int main()
 93 
 94 {
 95 
 96     freopen("input.txt","r",stdin);
 97 
 98     freopen("output.txt","w",stdout);
 99 
100     n=read()+1;
101     for2(i,2,n)
102     {
103         char ch=getchar();
104         while(ch!='p'&&ch!='j')ch=getchar();
105         a[i]=a[i-1]+(ch=='p'?1:-1);
106     }
107     int top=0;
108     a[n+1]=-inf;
109     for1(i,n+1)
110     {
111         while(top&&a[sta[top]]>a[i])r[sta[top--]]=i-1;
112         sta[++top]=i;
113     }
114     top=0;a[0]=inf;
115     for3(i,n,0)
116     {
117         while(top&&a[sta[top]]<a[i])l[sta[top--]]=i+1;
118         sta[++top]=i;
119     }
120     for1(i,n)add(l[i],i);
121     int ans=0;
122     for1(x,n)
123     {
124         for4(i,x)change(1,1,n,y);
125         ans=max(ans,query(1,1,n,x,r[x])-x);
126         //cout<<x<<' '<<a[x]<<' '<<l[x]<<' '<<r[x]<<' '<<query(1,1,n,x,r[x])-x<<endl;
127     }
128     cout<<ans<<endl;
129 
130     return 0;
131 
132 }  
View Code

 

         

posted @ 2015-01-29 07:42  ZYF-ZYF  Views(920)  Comments(0Edit  收藏  举报