ZROI2018提高day4t3

传送门

分析

我们假设如果一个点是0则它的值为-1,如果一个点是1则值为1,则一个区间的答案便是max(pre[i]+sur[i]),这里的pre[i]表示此区间i点和它之前的的前缀的最大值,sur[i]表示i点之后的后缀最大值。所以为了维护每个区间的答案我们可以用线段树进行维护。而对于一个由两个区间拼成的区间它的答案只有三种

1. 由左区间所选的pre加上右区间的sur

2. 由左区间的全部加上右区间的pre和sur

3. 由左区间所选的pre和sur加上右区间的全部

而这个区间的答案即为这三种的最大值。

至于为什么是这三种情况请自行画图思考。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
char s[200100];
int a[200100];
struct node {
      int pre,sur,ans,sum;
};
node d[800400];
inline void up(int wh){
      d[wh].sum=d[wh<<1].sum+d[wh<<1|1].sum;
      d[wh].pre=max(d[wh<<1].pre,d[wh<<1].sum+d[wh<<1|1].pre);
      d[wh].sur=max(d[wh<<1|1].sur,d[wh<<1|1].sum+d[wh<<1].sur);
      d[wh].ans=max(d[wh<<1].pre+d[wh<<1|1].sur,
      max(d[wh<<1].sum+d[wh<<1|1].ans,d[wh<<1].ans+d[wh<<1|1].sum));
      return;
}
inline void build(int le,int ri,int wh){
      if(le==ri){
          d[wh].ans=d[wh].pre=d[wh].sur=max(a[le],0);
          d[wh].sum=a[le];
          return;
      }
      int mid=(le+ri)>>1;
      build(le,mid,wh<<1);
      build(mid+1,ri,wh<<1|1);
      up(wh);
      return;
}
inline node q(int le,int ri,int wh,int x,int y){
      if(le>=x&&ri<=y)return d[wh];
      int mid=(le+ri)>>1;
      node ans,a,b;
      int cnt=0;
      if(mid>=x)cnt++,ans=a=q(le,mid,wh<<1,x,y);
      if(mid<y)cnt++,ans=b=q(mid+1,ri,wh<<1|1,x,y);
      if(cnt==1)return ans;
      ans.sum=a.sum+b.sum;
      ans.pre=max(a.pre,a.sum+b.pre);
      ans.sur=max(b.sur,b.sum+a.sur);
      ans.ans=max(a.pre+b.sur,max(a.sum+b.ans,a.ans+b.sum));
      return ans;
}
int main(){
      int n,m,i,j,k,x,y;
      scanf("%d%d",&n,&m);
      scanf("%s",s);
      for(i=1;i<=n;i++)
        if(s[i-1]=='0')a[i]=-1;
          else a[i]=1;
      build(1,n,1);
      for(i=1;i<=m;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          printf("%d\n",q(1,n,1,x,y).ans);
      }
      return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/9688569.html