bzoj
考慮詢問,如果我們把相互匹配的括號刪除,那麼我們最終會得到形如)))(的序列。
對於這樣乙個序列,我們不妨貪心。將左邊連續的l個右括號,從第乙個到(l+1)/2分別改為左括號。對右邊則反之。
那麼當l為偶數時,左邊會變得合法。當l為奇數時,會多餘乙個左括號,但由於題目保證了有解,即l+r為偶數,這個多餘的左括號將與右邊的多餘右括號匹配。
這樣顯然是沒有冗餘操作的。
這裡用了乙個小trick,可以只需要維護左右最大子段和即可。
注意replace操作可以覆蓋swap和invert操作,因為會使得這兩個操作沒有意義。
用了無旋treap實現,**寫起來還是短一些。
#include
#include
#include
using
namespace
std;
const
int maxn=100010;
int n,m,sz,rt,a,b,c,ans,val[maxn],rnd[maxn],s[maxn],ch[maxn][2],f[maxn];
int l[maxn],r[maxn],sum[maxn],lazy[maxn],rev[maxn],inv[maxn];
char op[10],ss[maxn];
inline
int max(int x,int y)
inline
int min(int x,int y)
void pushup(int x)
void pushdown(int x)
if(r)
lazy[x]=0;
}if(inv[x])
if(r)
inv[x]=0;
}if(rev[x])
}int merge(int x,int y)
if(lazy[x]||inv[x]||rev[x]) pushdown(x);
if(lazy[y]||inv[y]||rev[y]) pushdown(y);
if(rnd[x]1]=merge(ch[x][1],y);pushup(x);
return x;
}else
}void split(int now,int k,int &x,int &y)
if(lazy[now]||inv[now]||rev[now]) pushdown(now);
if(k<=s[ch[now][0]]) y=now,split(ch[now][0],k,x,ch[now][0]);
else x=now,split(ch[now][1],k-s[ch[now][0]]-1,ch[now][1],y);
pushup(now);
}int main()
else
if(op[0]=='s') rev[b]^=1,swap(l[b],r[b]),swap(ch[b][0],ch[b][1]);
else
if(op[0]=='i')
else
if(op[0]=='q')
rt=merge(merge(a,b),c);
}return
0;}
Bzoj2329 HNOI2011 括號修復
傳送門 答案就是去掉匹配的括號後的左邊右括號個數 2 2取下整和右邊左括號個數 2 2取下整 維護 設 為 1 role presentation style position relative 1 1,為1 role presentation style position relative 1 1...
BZOJ2329 HNOI2011 括號修復
bzoj luogu 你需要維護乙個括號序列,支援如下四種操作 1 把區間 l,r 全部改成 或是 2 把區間 l,r 翻轉。3 把區間 l.r 反轉,即 變 變 4 查詢區間 l,r 至少要修改幾個括號才能全部匹配。乙個區間的括號去掉匹配後一定長成 這個樣子。所以答案就是未匹配左括號個數 2 未匹...
bzoj2329 HNOI2011 括號修復
time limit 40 sec memory limit 128 mb submit 1232 solved 581 submit status discuss 分析 第一次做覺得這道題好神啊!思維量和 量都驚人!今天早上又花20min碼了一次,覺得這只不過是乙個套路題罷了.這道題實際上是由兩個...