hdu5217 括號序列 線段樹

2022-05-31 07:36:12 字數 1724 閱讀 9177

題意:給一串括號,有2個操作,1。翻轉某個括號。2。查詢某段區間內化簡後第k個括號是在原序列中的位置。1≤n,q≤200000.

題解:可以知道,化簡後的序列一定是)))((((這種形式的。

線段樹每個節點就存對應區間內化簡後的ls也就是)的數量,rs也就是(的數量。

然後我先把區間[l,r]找出來合併一遍,找出第k個是哪一種擴號。

問題轉化為找區間[l,r]中的第kk個左擴號或者右括號。

我們可以發現,如果是)這種括號,區間從左到右合併的時候是單調不減的。

同理,(這種括號,區間從右往左合併的時候也是單調不減的。

然後我是變成從左往右的第kk個),或者從右往左的第kk個(。

細節挺多的。

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;78

const

int n=200010;9

intn,m,tl,cl,c[n];

10char

s[n];

11struct

nodet[2*n];

1415

int maxx(int x,int y)

1617

node upd(node x,node lc,node rc)

1828

29int bt(int l,int

r)30

43else

4448

return

x;49}50

51void change(int x,int

p)52

54int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)/2;55

if(p<=mid) change(lc,p);

56else

change(rc,p);

57 t[x]=upd(t[x],t[lc],t[rc]);58}

5960

void query(int x,int l,int

r)61

63int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)/2;64

if(r<=mid) query(lc,l,r);

65else

if(l>mid) query(rc,l,r);

66else

6771}72

73int fd(int x,int k,int

tmp)

7482

else

8387}88

89int

main()

90109

else

110116

if(now.ls>=k)

117130 p0=p1;

131}

132}

133}

134else

135145 p0=p1;

146}

147}

148}

149 printf("

%d\n

",ans);

150}

151}

152}

153return0;

154 }

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

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

序列 線段樹

使用線段樹維護 b bb,初值為 bi b i bi 每次修改時,若乙個位置上的值變為了 0 00,則說明其會對答案產生新的貢獻,在外部使用樹狀陣列將貢獻計入答案,然後將該位置的值 重置為 bi b i bi 重置的時間複雜度是 o log n o log n o logn 考慮最壞情況,每次操作 ...

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

給定乙個長度為 n 的括號序列,要求支援兩種操作 將 l,r 區間內的括號全部翻轉 求出以 l 為左端點時,最長的合法括號序列對應的 r 1 n 10 6 1 m 2 10 5 首先根據這個資料範圍,要想到線段樹 當 s i a i 1 當 s i a i 1 乙個顯然的想法是建立乙個線段樹,其節點...