圣章-精灵使的魔法语

题目

【题目描述】
“伦福萨”【即” ( “】和“密西卡”【即” ) “】是两种不同的精灵咒语,已知一个成功的咒语符合如下的规定:
每一个密西卡之前都可以对应匹配到一个伦福萨,即为一个合法的精灵魔法咒语。
方便的是,我们将“伦福萨”视为” ( “,“密西卡”视为” ) “,合法的精灵魔法咒语即为一个合法的括号序列。
如:” ( ( ( ) ) ) “” ( ( ) ( ) ) “” ( ) ( ) ( ) “均为合法的魔法咒语,” ) ( “” ( ) ) ( “” ( ( “均为不合法的魔法咒语。
现在弗洛莉给我一个长长的“伦福萨”【即” ( “】和“密西卡”【即” ) “】的片段,每次给我一个l和r,让我判断需要在这个片段前最少添多少个“伦福萨”【即” ( “】,以及最少添多少个“密西卡”【即” ) “】可以成为一个合法的魔法咒语,更令人不爽的是,弗洛莉有的时候还会把一个“伦福萨”【即” ( “】变成“密西卡”【即” ) “】,或把一个“密西卡”【即” ) “】变为“伦福萨”【即” ( “】。

题意

给你一个括号序列,可以修改,问一段区间里面的需要添加的左括号和右括号数

分析

修改,求区间的询问,我们可以用线段树维护
那么线段树维护什么值呢?
我们又可以直接维护答案要求的东西:
1.这个区间里面要加多少个左括号(即这个区间需要多少个左括号)
2.这个区间里面要加多少个右括号(即这个区间多余多少个左括号)
合并区间就是:
这个区间
需要的左括号=左半边需要的左括号+max(右边需要的左括号-左边多余的左括号,0)
多余的左括号=右边多余的左括号+max(左边多余的左括号-右边需要的左括号,0)

    tree[v].l=tree[v*2].l+max(tree[v*2+1].l-tree[v*2].r,0);
    tree[v].r=tree[v*2+1].r+max(tree[v*2].r-tree[v*2+1].l,0);

其他的就变得简单了

但是还要注意的是答案的计算。
因为我们最后得到的是一个区间的被分散的区间合在一起的答案(即find里面),那么我们如何合并呢?
因为线段树的合并是有序的,那么我们便可以用类似的合并操作(即上面)这个区间与上一个区间合并的值再与下一个区间合并,这样才不会出现错误,才是正确的。
这就是区间求答案的过程:
ans1为需要左括号
ans2为多余左括号
tree[v].l为需要的
tree[v].r为多余的

void query(int v,int l,int r,int x,int y)
{
    if(l==x && r==y)
    {
        ans1+=max(tree[v].l-ans2,0);
        ans2=tree[v].r+max(ans2-tree[v].l,0);
        return;
    }
    int mid=(l+r)>>1;
    if(y<=mid) query(v*2,l,mid,x,y);
    else
    if(x>mid) query(v*2+1,mid+1,r,x,y);
    else
    {
        query(v*2,l,mid,x,mid);
        query(v*2+1,mid+1,r,mid+1,y);
    }
}

ps:
很快就NOIP了,感觉自己还没准备好。。。
加油!祝大家NOIP,RP++

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值