日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 默认站点!

默认站点

當前位置: 首頁 >

jzoj4273-圣章-精灵使的魔法语【线段树】

發布時間:2023/12/3 39 豆豆
默认站点 收集整理的這篇文章主要介紹了 jzoj4273-圣章-精灵使的魔法语【线段树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


大意

有n個括號,有左有右,求一個區間內有多少個括號不能相互匹配。中間會改變某些括號的方向。


解題思路

線段樹維護兩個數lm(left?moreleftmore),rm(right?morerightmore)分別表示這個區間內多余的左括號和多余的右括號(是能相互匹配的,如“)()(”這兩個括號就不能相互匹配)。然后我們需要考慮兩段區間如何合并。

我們想一下,已經計算好的一個區間中的左括號是不能和右括號相互匹配的,但是在它右邊的區間中的所有多余的右括號都能和這個區間中的左括號相互匹配,所以我們可以得到:

t[x].lm=t[x?2+1].lm+max(0,t[x?2].lm?t[x?2+1].rm)t[x].lm=t[x?2+1].lm+max(0,t[x?2].lm?t[x?2+1].rm)
相反,在這個區間的左邊的區間內所有的左邊括號都可以和這個區間內的右括號相互匹配:
t[x].rm=t[x?2].rm+max(0,t[x?2+1].rm?t[x?2].lm)t[x].rm=t[x?2].rm+max(0,t[x?2+1].rm?t[x?2].lm)
然后維護查詢修改都是正常操作


代碼

#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define MN 150001 using namespace std; struct tnode{int rm,lm,l,r; }t[MN*4]; int n,m,x,y,anl,anr,zal,zar; char c[7],str[MN]; void build(int x,int l,int r){t[x].l=l;t[x].r=r;if (l==r) {t[x].lm=str[l]=='('?1:0;t[x].rm=str[l]==')'?1:0;return;}int mid=(l+r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);t[x].lm=t[x*2+1].lm+max(0,t[x*2].lm-t[x*2+1].rm);t[x].rm=t[x*2].rm+max(0,t[x*2+1].rm-t[x*2].lm);//維護 } void updata(int x,int z) {if (t[x].l==z&&t[x].r==z){t[x].rm^=1,t[x].lm^=1;return;}int mid=(t[x].l+t[x].r)>>1;if (z<=mid) updata(x<<1,z);else updata(x<<1|1,z);t[x].lm=t[x*2+1].lm+max(0,t[x*2].lm-t[x*2+1].rm);t[x].rm=t[x*2].rm+max(0,t[x*2+1].rm-t[x*2].lm);//維護 } void find(int x,int l,int r) {if (t[x].l==l&&t[x].r==r){anl+=max(0,t[x].rm-anr);anr=t[x].lm+max(0,anr-t[x].rm);//累計return;}int mid=(t[x].l+t[x].r)>>1;if (r<=mid) find(x<<1,l,r);else if (l>mid) find(x<<1|1,l,r);else {find(x<<1,l,mid);find(x<<1|1,mid+1,r);} } int main() {//freopen("elf.in","r",stdin);//freopen("elf.out","w",stdout);scanf("%d%d",&n,&m);scanf("%s",str+1);build(1,1,n);for (int i=1;i<=m;i++){scanf("%s",c+1);if (c[1]=='Q'){scanf("%d%d",&x,&y);find(1,x,y);printf("%d %d\n",anl,anr);anl=0;anr=0;}else{scanf("%d",&x);updata(1,x);}} }

總結

以上是默认站点為你收集整理的jzoj4273-圣章-精灵使的魔法语【线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得默认站点網站內容還不錯,歡迎將默认站点推薦給好友。