藍橋杯 翻轉括號序列 題解 線段樹 思維

2022-09-24 04:51:09 字數 1204 閱讀 1649

給定乙個長度為 \(n\) 的括號序列,要求支援兩種操作:

將\([l,r]\) 區間內的括號全部翻轉

求出以\(l\)為左端點時,最長的合法括號序列對應的\(r\)

\(1 ≤ n ≤ 10^6 , 1 ≤ m ≤ 2 × 10^5\)

首先根據這個資料範圍,要想到線段樹

當\(s[i]==( \;a[i]=1\)

當\(s[i]==) \;a[i]=-1\)

乙個顯然的想法是建立乙個線段樹,其節點的值為\(a\)陣列的字首和

那麼對於操作\(1\)如何修改是乙個問題,你會發現不好直接進行修改

可以把這個問題轉化為\([1,l-1]\)和\([1,r]\)修改兩次,顯然是等價的

那麼修改\([1,x]\)會使得\([1,x]\)中的元素乘以\(-1\),使得\([x+1,n]\)中的所有元素\(+2pre[x]\)

對於操作2顯然是要找到在\([l,n]\)中找到乙個最大的\(pos\)使得\(pre[pos]==pre[l-1]\)

並且在\([l,pos-1]\)中不存在\(pre[i]

這個問題比較麻煩,解決的方法也比較巧妙

首先找到\([l,n]\)中第乙個小於\(pre[l-1]\)的\(pos\),那麼答案必定在\([l,pos-1]\)中

再找到\([1,pos-1]\)中座標最接近\(pos-1\)且值小於\(pre[l-1]+1\)的位置

如果這個位置大於\(l\)顯然就是答案,否則為\(0\)

如何尋找\(pos\)就是線段樹上二分,需要維護區間的最大最小值

這個題目要關注的是有兩個\(lazy\)相互影響要注意寫法

#include#define fi first

#define se second

#define debug cout<<"i am here"// 邊界處理

if(l<=l&&r<=r)else if(op==2)

return ;

}updown(node);

int mid=(l+r)/2;

if(mid>=l) update(node<<1,l,r,l,mid,add,op);

if(mid=pos) now=query(node<<1,l,mid,pos);

if(mid=pos&&mi[node<<1]l)else}}

return 0;

}

線段樹yy(線段樹維護括號序列 LCA)

沒有題目鏈結 一顆有 n 個節點的樹,q 組詢問,支援兩種操作 1.單點修改 2.路徑求和。1 n,q 1e5 題解 那麼可以建立一顆有根樹,每次更新時為兩個單點更新 加一次減一次 每次查詢時則是查詢 根的左括號到 x 點的左括號之和 根的左括號到 y 點的左括號之和 2 根的左括號到 x 與 y ...

藍橋杯 操作格仔 線段樹

題目 有n個格仔,從左到右放成一排,編號為1 n。共有m次操作,有3種操作型別 1.修改乙個格仔的權值,2.求連續一段格仔權值和,3.求連續一段格仔的最大值。對於每個2 3操作輸出你所求出的結果。輸入格式 第一行2個整數n,m。接下來一行n個整數表示n個格仔的初始權值。接下來m行,每行3個整數p,x...

藍橋杯 操作格仔 線段樹

剛學習了線段樹,解決區間問題確實是不錯的利器,線段樹實際上就是一棵平衡二叉樹,對於任何操作都能在o long2n 的時間內完成,相比對普通陣列o n 的時間複雜度,有不錯的效率,下面以藍橋網上乙個題操練一下吧。問題描述 有n個格仔,從左到右放成一排,編號為1 n。共有m次操作,有3種操作型別 1.修...