第三届中国计量大学ACM程序设计竞赛 L-线段树维护前缀最小值

题目链接:https://ac.nowcoder.com/acm/contest/5795/L
给你长度为n的一个扩号序列。m次修改,每次修改把第x个扩号取反方向。并且修改后询问扩号序列是否合法。
图片说明
思路:用一个线段树维护这个扩号序列
'(':-1
')':1
每次修改其实就是一个单点修改。如果前缀和<0那么就不合法。如果前缀和>0并且1-n的和为0就合法。

#include <bits/stdc++.h>
using namespace std;

char s[100005];
int sum[4*100005], mi[4*100005];
void gx(int i, int l, int r, int x, int y){
    if(l==r){
        sum[i]=y; return ;
    }
    if(x<=(l+r)/2) gx(i<<1, l, l+r>>1, x, y);
    else gx(i<<1|1, (l+r>>1)+1, r, x, y);
    sum[i]=sum[i<<1]+sum[i<<1|1];
    mi[i]=min(mi[i<<1], mi[i<<1|1]+sum[i<<1]);//维护前缀最小值
}

int main(){

    int n, m;
    scanf("%d%d", &n, &m);
    scanf("%s", s+1);
    for(int i=1; i<=n; i++){
        if(s[i]=='(') gx(1, 1, n, i, 1);
        else gx(1, 1, n, i, -1);
    }
    while(m--){
        int x; scanf("%d", &x);
        if(s[x]=='('){
            gx(1, 1, n, x, -1); s[x]=')';
        }
        else{
            gx(1, 1, n, x, 1);  s[x]='(';
        }
        if(sum[1]==0&&mi[1]>=0){
            printf("Yes\n");
        }
        else{
            printf("No\n");
        }
    }

    return 0;
}
全部评论

相关推荐

frutiger:逆天,我家就安阳的,这hr咋能说3k的,你送外卖不比这工资高得多?还说大厂来的6k,打发叫花子的呢?这hr是怎么做到说昧良心的话的
找工作时遇到的神仙HR
点赞 评论 收藏
分享
06-15 02:05
已编辑
南昌航空大学 数据分析师
Eason三木:你如果想干技术岗,那几个发公众号合唱比赛的经历就去掉,优秀团员去掉,求职没用。然后CET4这种不是奖项,是技能,放到下面的专业技能里或者单独列一个英语能力。 另外好好改改你的排版,首行缩进完全没有必要,行间距好好调调,别让字和标题背景黏在一起,你下面说能做高质量PPT你得展现出来啊,你这简历排版我用PPT做的都能比你做的好。 然后自我评价,你如果要干数据工程师,抗压能力强最起码得有吧。
简历中的项目经历要怎么写
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务