2018湖南多校第五场-20180506 训练日志

solved 5 (a b d f g)

rank 5/28

 

总体发挥较佳,虽然中期卡在了D,最后成绩还是完成了flag。dzcjj太强辣。

最直观的感受就是觉得时间不够用,这比之前做完水题就挂机的水平还是有很强的提高的。

 

Bit String Reordering(暴搜)

 

Miscalculation(模拟)

<qj>

本场最水的一道题,完全码力题。

题意:给一个字符串,里面包含了一些数学运算的式子,求两种定义下的值。(只存在加法和乘法)

第一种定义:先乘除后加减。

第二种定义:从左至右运算。

解法:模拟一下便可。(第一种可以用到stack来解决,第二种可以直接搞,当然也可以用queue)

 

Space Golf(推物理公式)

 

There is No Alternative(最小生成树相关)

 

Flipping Parentheses (线段树 + 二分)

<qj>

题意:

给一个初始的字符串,由左括号和右括号组成,保证初始字符串平衡。

q个查询,翻转第pos个括号,问你翻转哪一个最靠左的括号能够使序列重新平衡。

每次操作会影响到后面的操作。

 

思路:

遇到括号平衡的问题,我们一般会想到前缀和表达,但这个题里存在翻转(修改)的操作,那么不难想到,能够实现前缀和 + 修改 的数据结构有线段树或树状数组。

由于性质,最后一个括号一定是 ‘)’ ,且prefix(最后一个)值为0, 才会平衡。

1.

如果翻转了一个 ')',那么从pos开始到结尾的前缀和应该都 +2 ,我们可以用线段树把这个区间的值都 +2 。

已知串要平衡,最后一个位置前缀和应该是 0 ,而目前最后一个位置是 2。

那么我们需要找到一个pos2,pos2翻转,使得[pos2,n]区间 -2。

然后这里为了不破坏平衡,区间内所有值都必须大于等于2。所以线段树可以去维护一个区间最小值,若区间最小值不小于2,该区间满足条件。

怎么找到最左的pos呢,我们可以用到二分搜索。

int l = 0, r = n+1;int mid  = l+r>>1;

如果mid往右的所有前缀和满足条件,那么我们往左找[l,mid],否则往右找[mid,n]。

复杂度 O(Q*logN*logN)

 

2.

如果翻转了‘(’ , 跟上面是类似的。最后一个位置的前缀和应该是 -2。

如何找到最左的一个括号翻转,并使得最后一个位置前缀和变成0呢?

翻转从左开始第一个‘)’便可。

若前面全是'('不难知道,在第pos个位置,prefix(pos)==pos,说明前面没有出现过')' 。

同上,二分去找第一个prefix(pos)!=pos的位置就可以了。

复杂度 O(Q*logN*logN)

 

上代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 300055
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define intmid  int mid = (l+r)>>1
int n,q;
char s[maxn];
int pre[maxn];
int cur[maxn<<2],minv[maxn<<2];
void push_up(int rt){
    minv[rt] = min(minv[rt<<1] , minv[rt<<1|1]);
}

void push_down(int l,int r,int rt){
    if(cur[rt]){
        intmid;
        cur[rt<<1]  += cur[rt];
        cur[rt<<1|1]+= cur[rt];
        minv[rt<<1]  += cur[rt];
        minv[rt<<1|1]+= cur[rt];
        cur[rt]=0;
    }
}

void build(int l,int r,int rt){
    intmid;
    cur[rt]=0;
    if(l==r){
        minv[rt]=pre[l];
        return ;
    }
    push_down(l,r,rt);
    build(lson);build(rson);
    push_up(rt);
}

void update(int ll,int rr,int val,int l,int r,int rt){
    intmid;
    if( ll<=l && rr>=r ){
        cur[rt]+=val;
        minv[rt]+=val;
        return ;
    }
    push_down(l,r,rt);
    if(ll<=mid)update(ll,rr,val,lson);
    if(rr>mid)update(ll,rr,val,rson);
    push_up(rt);
}

int querymin(int ll,int rr,int l,int r,int rt){
    int ret=0x3f3f3f3f;
    if(ll<=l && rr>=r){
        return minv[rt];
    }
    push_down(l,r,rt);
    intmid;
    if(ll<=mid) ret = min(ret,querymin(ll,rr,lson));
    if(rr>mid) ret = min(ret,querymin(ll,rr,rson));
    return ret;
}

bool check(int pos){
    int v = querymin(pos,n,1,n,1);
    if(v<2)return 1;
    return 0;
}

bool check2(int pos){
    int v = querymin(pos,pos,1,n,1);
    if(v==pos)return 1;
    return 0;
}

int main(){
    while(scanf("%d%d",&n,&q)!=EOF){
        scanf("%s",s+1);
        for(int i=1;i<=n;i++){
            pre[i]=pre[i-1];
            if(s[i]=='(')pre[i]++;
            else pre[i]--;
        }
        build(1,n,1);
        while(q--){
            int pos;
            scanf("%d",&pos);
            if(s[pos]=='('){
                s[pos]=')';
                update(pos,n,-2,1,n,1);
                int l=0,r=n+1;
                while(l<r-1){
                    intmid;
                    if(check2(mid)){
                        l=mid;
                    }
                    else r=mid;
                }
                printf("%d\n",r);
                s[r]='(';
                update(r,n,2,1,n,1);

            } else{
                s[pos]='(';
                update(pos,n,2,1,n,1);
                int l=0,r=n+1;
                while(l<r-1){
                    intmid;
                    if(check(mid)){
                        l=mid;
                    }
                    else r=mid;
                }
                printf("%d\n",r);
                s[r]=')';
                update(r,n,-2,1,n,1);
            }
        }
    }
    return 0;
}

 

posted on 2018-05-07 11:27  鹤鸣于九皋,声闻于天  阅读(143)  评论(0编辑  收藏  举报

导航