圣章-精灵使的魔法语

来源:互联网 发布:ios 彩票项目源码 编辑:程序博客网 时间:2024/03/29 15:49

题目

【题目描述】
“伦福萨”【即” ( “】和“密西卡”【即” ) “】是两种不同的精灵咒语,已知一个成功的咒语符合如下的规定:
每一个密西卡之前都可以对应匹配到一个伦福萨,即为一个合法的精灵魔法咒语。
方便的是,我们将“伦福萨”视为” ( “,“密西卡”视为” ) “,合法的精灵魔法咒语即为一个合法的括号序列。
如:” ( ( ( ) ) ) “” ( ( ) ( ) ) “” ( ) ( ) ( ) “均为合法的魔法咒语,” ) ( “” ( ) ) ( “” ( ( “均为不合法的魔法咒语。
现在弗洛莉给我一个长长的“伦福萨”【即” ( “】和“密西卡”【即” ) “】的片段,每次给我一个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 0