• #603(div 2)


    603(div 2)

    E .Editor

    • 题意: 输入一串字符串,由( ,), L,R 和其他字符组成。

    • 分析:

      • 首先要知道这几点,( 一 )对于括号匹配问题我们一般让左括号表示(+1) ,右括号表示(-1) 。这样如果前缀和为0表示左右括号都合理的匹配了。( 二 ) 跟据题意最后左右括号的最大嵌套数是所需的颜色数,由于从左向右先遇到左括号,一直+1.所以前缀和最大值为所需的颜色数。
      • 什么时候是 “ 很好 ” 的匹配?应该是所有的左右括号都有匹配,即任何一个前缀和都大于等与0,也就是 前缀和的最小值为0 。同时为了保证所有左右括号都匹配了,要求 第n个前缀和为0。 此时我们输出的结果是 前缀和最大值 。 不满足括号全部匹配就输出-1。
      • 那么由于在遍历字符串指行各种指令时会修改位置各个值,即动态修改然后问你结果。这就要用数据结构——线段树。本题需要维护三个值即上面加粗的三个值。
      • 这道题其实很好的作为线段树模板题。体现了线段数维护动态修改时的作用。很快会写一个关于线段树的博客。
    • 代码:

      #include<bits/stdc++.h>
      using namespace std;
      typedef long long ll;
      const int MA=1e6+5;
      const int INF=0x3f3f3f3f;
      
      struct node
      {
          int l,r;
          int sum;
          int mx;
          int mn;
          int add;
      }tree[MA*4+5];
      
      void Pushup(int index)
      {
          tree[index].sum=tree[index<<1].sum+tree[index<<1|1].sum;
          tree[index].mx=max(tree[index<<1].mx,tree[index<<1|1].mx);
          tree[index].mn=min(tree[index<<1].mn,tree[index<<1|1].mn);
      }
      
      void Pushdown(int index)
      {
          if(tree[index].add){
              tree[index<<1].sum+=(tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
              tree[index<<1|1].sum+=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
              tree[index<<1].mx+=tree[index].add;
              tree[index<<1|1].mx+=tree[index].add;
              tree[index<<1].mn+=tree[index].add;
              tree[index<<1|1].mn+=tree[index].add;
              tree[index<<1].add+=tree[index].add;
              tree[index<<1|1].add+=tree[index].add;
              tree[index].add=0;
          }
      }
      
      void Build(int l,int r,int index)
      {
          tree[index].l=l;
          tree[index].r=r;
          tree[index].add=0;
          if(l==r){
              scanf("%d",&tree[index].sum);
              tree[index].mx=tree[index].mn=tree[index].sum;
      
              return ;
          }
          int mid=(l+r)>>1;
          Build(l,mid,index<<1);
          Build(mid+1,r,index<<1|1);
          Pushup(index);
      }
      
      void Updata(int l,int r,int index,int val)
      {
          if(l<=tree[index].l&&tree[index].r<=r){
             tree[index].sum+=(tree[index].r-tree[index].l+1)*val;
             tree[index].mx+=val;
             tree[index].mn+=val;
             tree[index].add+=val;
      
             return ;
          }
          Pushdown(index);
          int mid=(tree[index].l+tree[index].r)>>1;
          if(l<=mid) Updata(l,r,index<<1,val);
          if(mid<r) Updata(l,r,index<<1|1,val);
          Pushup(index);
      }
      
      int querySum(int l,int r,int index)
      {
         if(l<=tree[index].l&&tree[index].r<=r){
              return tree[index].sum;
         }
         Pushdown(index);
         int Sum=0;
         int Max=0;
         int Min=INF;
         int mid=(tree[index].l+tree[index].r)>>1;
         if(l<=mid) Sum+=querySum(l,r,index<<1);
         if(mid<r) Sum+=querySum(l,r,index<<1|1);
         return Sum;
      }
      
      int queryMx(int l,int r,int index)
      {
         if(l<=tree[index].l&&tree[index].r<=r){
              return tree[index].mx;
         }
         Pushdown(index);
         int Sum=0;
         int Max=0;
         int Min=INF;
         int mid=(tree[index].l+tree[index].r)>>1;
         if(l<=mid) Max=max(Max,queryMx(l,r,index<<1));
         if(mid<r) Max=max(Max,queryMx(l,r,index<<1|1));
         return Max;
      }
      
      
      int queryMn(int l,int r,int index)
      {
         if(l<=tree[index].l&&tree[index].r<=r){
              return tree[index].mn;
         }
         Pushdown(index);
         int Sum=0;
         int Max=0;
         int Min=INF;
         int mid=(tree[index].l+tree[index].r)>>1;
         if(l<=mid) Min=min(Min,queryMn(l,r,index<<1));
         if(mid<r) Min=min(Min,queryMn(l,r,index<<1|1));
         return Min;
      }
      
      string s;
      int ss[MA];
      int main()
      {
          int n;
          scanf("%d",&n);
          n=n+5;
          Build(1,n,1);
          cin>>s;
          int pos=1;
          vector<int>ans;
          for(int i=0;i<s.size();++i){
              if(s[i]=='('){
                  Updata(pos,n,1,1-ss[pos]);
                  ss[pos]=1;
              }
              else if(s[i]==')'){
                  Updata(pos,n,1,-1-ss[pos]);
                  ss[pos]=-1;
              }
              else if(s[i]=='L'){
                  if(pos>1) pos--;
              }
              else if(s[i]=='R'){
                  pos++;
              }
              else{
                  if(ss[pos]==1){
                      Updata(pos,n,1,-1);
                  }
                  else if(ss[pos]==-1){
                      Updata(pos,n,1,1);
                  }
                  ss[pos]=0;
              }
      
              if(queryMn(1,n,1)==0&&querySum(n,n,1)==0){
                  ans.push_back(queryMx(1,n,1));
              }
              else ans.push_back(-1);
          }
          for(int i=0;i<ans.size();++i){
              printf("%d ",ans[i]);
          }
          printf("
      ");
          return 0;
      }
      
      
  • 相关阅读:
    vue中封装axios方法
    ajax请求步骤
    angular 封装公共方法
    vue 二级列表折叠面板
    eslint常规语法检
    angular 4 路由变化的时候实时监测刷新组件
    json写入到excel表
    angular4 常用pipe管道
    angular4 在页面跳转的时候传递多个参数到新页面
    easyui 动态加载语言包
  • 原文地址:https://www.cnblogs.com/A-sc/p/12189641.html
Copyright © 2020-2023  润新知