zoukankan      html  css  js  c++  java
  • CSUOJ 1542 线段树解决括号反向问题

    题目大意:

    根据初始给定的合法的小括号排序,每次进行一个操作,将第a位的括号反向,找到一个尽可能靠前的括号反向后是整个括号排列合法

    数据量十分大,不断进行查询,要用线段树进行logn的复杂度的查询

    首先最简单的考虑 '('->')' ,  稍微想一下可以知道因为要尽可能靠前,所以其实把最前面的那个 )改成 ( 即可,这里我就用 minn[] 数组记录区间内最早出现的 ) 的下标

    然后是考虑 ')'->'(' , 我们可以倒着字符串来看,从后往前每次出现一个 ) 都记录加1 , 那么每次遇到一个 ( 就抵消1 , 那么当遇到 (没东西抵消时,说明这个是离尾部最远的不合法的符号,离尾部最远,那么就可以理解为离起点最近

    具体怎么写的话就是可以将 '(' 看作 1 , ')' 看作-1 , 利用一个数组 minsum[] 记录区间内前缀和的最小值

    对于一个线段树来说如果那个符号的位置出现在左子树的区间上,那么右子树中的所有前缀和都必然 >=2

    所以查询就很容易得到 if(sum[rs] < 2) ans = 右子树的查询,else ans = 左子树的查询

    但再想想的话,返回的值不能是当前下标 , 而是下标+1;

    因为根据前面所讲,你所需要修改的位置 i 是 i 后面的数相加和正好为0的

    也就是说到达i的前缀之和正好是2

    而 第 i-1 位的前缀和正好为1,每次不断判断找   < 2的点,那么最后查询到的是i-1

    也就是必须要加个1才能到达我需要改的位置

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 using namespace std;
      5  
      6 #define ls o<<1
      7 #define rs o<<1|1
      8 #define define_m int m=(l+r)>>1
      9 const int N = 300010;
     10 const int INF = 0x3f3f3f3f;
     11 int minn[N<<2] , minsum[N<<2] , a[N] , add[N<<2];
     12 char str[N];
     13  
     14 void push_up(int o)
     15 {
     16     minsum[o]=min(minsum[ls] , minsum[rs]);
     17     minn[o]=min(minn[ls] , minn[rs]);
     18 }
     19  
     20 void push_down(int o)
     21 {
     22     if(add[o]){
     23         add[ls]+=add[o];
     24         add[rs]+=add[o];
     25         minsum[ls]+=add[o];
     26         minsum[rs]+=add[o];
     27         add[o]=0;
     28     }
     29 }
     30  
     31 void build(int o , int l , int r)
     32 {
     33     add[o]=0;
     34     if(l == r) {
     35         minn[o] = str[l]==')'?l:INF;
     36         minsum[o]=a[l];
     37         return;
     38     }
     39     define_m;
     40     build(ls , l , m);
     41     build(rs , m+1 , r);
     42     push_up(o);
     43 }
     44  
     45 void update(int o , int l , int r , int s , int t , int v)
     46 {
     47     if(l>=s && r<=t){
     48         minsum[o]+=v;
     49         add[o]+=v;
     50         return;
     51     }
     52     push_down(o);
     53     define_m;
     54     if(m>=s) update(ls , l , m , s , t , v);
     55     if(m<t) update(rs , m+1 , r ,s , t , v);
     56     minsum[o]=min(minsum[ls] , minsum[rs]);
     57 }
     58  
     59 void update1(int o , int l , int r , int pos)
     60 {
     61     if(l == r && l == pos){
     62         minn[o] = (str[l]==')'?l:INF);
     63         return;
     64     }
     65     push_down(o);
     66     define_m;
     67     if(m >= pos) update1(ls , l , m ,pos);
     68     else update1(rs , m+1 , r , pos);
     69     minn[o] = min(minn[ls] , minn[rs]);
     70 }
     71  
     72 int query(int o , int l , int r , int n)
     73 {
     74    // cout<<"o: "<<o<<" l: "<<l<< " r: "<<r<<" left: "<<minsum[ls]<<" right: "<<minsum[rs]<<endl;
     75     if(l==r) return l+1;
     76     push_down(o);
     77     define_m;
     78     if(minsum[rs]<2) return query(rs , m+1 , r , n);
     79     else return query(ls , l , m , n);
     80 }
     81  
     82 int main()
     83 {
     84    // freopen("a.in" , "r" , stdin);
     85     int n , m , pos;
     86     while(scanf("%d%d" , &n , &m) != EOF)
     87     {
     88         scanf("%s" , str+1);
     89         for(int i=1 ; i<=n ; i++){
     90             a[i]=a[i-1]+(str[i]=='('?1:-1);
     91         }
     92         build(1 , 1 , n);
     93         int res;
     94         for(int i=0 ; i<m ; i++){
     95             scanf("%d" , &pos);
     96             if(str[pos] == '('){
     97                 str[pos] = ')';
     98                 update1(1 , 1 , n , pos);
     99                 update(1 , 1 , n , pos , n , -2);
    100                 res = minn[1];
    101                 str[res] = '(';
    102                 update1(1 , 1 , n , res);
    103             }
    104             else{
    105                 str[pos] = '(';
    106                 update1(1 , 1 , n , pos);
    107                 update(1 , 1 , n , pos , n , 2);
    108                 res = query(1 , 1 , n , n);
    109                 str[res] = ')';
    110                 update1(1 , 1 , n , res);
    111             }
    112             update(1 , 1 , n , res , n , str[res] == '('?2:-2);
    113             printf("%d
    " , res);
    114         }
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    [VBS]遍历XML文档
    [VBS]带参数删除扩展名不是*.h、*.c、*.cpp的全部文件
    [VBS]脚本中的字典、动态数组、队列和堆栈
    [VBS]检测计算机各硬件信息
    [cmd]如何设置 Windows 默认命令行窗口大小和缓冲区大小
    VB.NET and C# 差异
    host-only局域网络
    高并发、死锁、幂等性问题
    elasticsearch简单实现
    记一次504 Gateway Time-out
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4362424.html
Copyright © 2011-2022 走看看