BZOJ2329 HNOI2011括號修復

2021-08-20 03:51:24 字數 1611 閱讀 9895

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碼了一次,覺得這只不過是乙個套路題罷了.這道題實際上是由兩個...