bzoj4964 加長的咒語

2021-08-06 01:31:26 字數 1511 閱讀 4837

求區間最長匹配的括號序列子串。

很有意思的括號,但是我有些細節沒處理好,導致**長,演算法複雜。。 如果有更好的演算法我也很想知道啊》.<

考慮乙個括號序列a=(b1)(b2)(b3)…,其中與某個括號匹配的相對的括號唯一。證明顯然。

有乙個顯然的演算法:用棧判斷乙個字串是否為括號序列。

考慮拓展這個結論:對任意括號串的某個括號序列子串,某個括號匹配的相對的括號唯一。證明顯然。

既然這樣就隨便建一些()樹,每個節點表示一對匹配的括號,兒子表示在這對括號中的括號序列。

不妨只考慮詢問在同一顆()樹的(節點~)節點的答案。

如圖,詢問綠括號的答案,令u,v是深度大於lca的最淺的x,y的祖先。那麼(u,v)這一段都可以作為答案。對於答案不在這之中的情況,考慮選綠括號和不選綠括號。

選的方案容易得到,不選的方案相當於鏈上最大值。於是可以在o(nlogn+qlogn)的時間內得到答案。

如果是長鏈剖分可以達到o(nlogn+q)的毒瘤複雜度。

演算法瓶頸在於尋找uv,不知道有沒有更好的做法。

這裡有claris的題解

似乎這種括號匹配還能離線做,可以思考一下,想出來再更新吧。。

#include#define n 400005

using namespace std;

int n,q,id[n],l[n],r[n],lt[n],rt[n],fl[n],fr[n];

int rt[n],ly,f[n];

int fa[n][25],dep[n],v[n][25],vl[n][25],vr[n][25],cnt;

int st[n],top;

char s[n];

void build(int k,int l,int r)

if (l>r) return;

int t=l;

for (;l<=r;l=r[l]+1) }

int lg[n];

int qry(int x,int y)

for (int i=1;i<=q;i++)

ans=max(ans,rt[y]-max(lt[fa[y][0]],rt[x]));

}else if (dep[x]=0;t1>>=1,t2--)

ans=max(ans,min(rt[fa[x][0]],lt[y])-lt[x]);

}else

t1=1<<20;t2=20;

for (;t2>=0;t1>>=1,t2--)

ans=max(ans,lt[y]-rt[x]-1);

}else

t1=1<<20;t2=20;

for (;t2>=0;t1>>=1,t2--)

ans=max(ans,qry(f[x]+1,f[y]-1));

}} printf("%d\n",ans);

} }}

BZOJ4964 加長的咒語

把 看作 1 看作 1 設 a 為字首和,則相當於找兩個位置 x,y 使得 a x a y 且 a x 是 x,y 的區間最大值。求出詢問區間的最大值 o 然後找到 o 在該區間內最左和最右的出現位置,將其作為答案。那麼剩下的答案只可能在 l,o 或 o,r 以 l,o 為例。通過單調棧求出每個位置...

洛谷 P4964 綾小路的特別考試 解題報告

這世界上 勝利 便是一切。無關乎過程。要付出多少犧牲都無所謂。只要最後我 勝出 那就行了。一場新的特別考試來臨了,這次的考試內容是 wan e de 文化課,但有所不同的是,考試中允許學生使用對講機。然而,對講機的接收範圍有限 每個對講機都能傳送無限遠,但是只能接收到接收範圍內的訊號 所以,需要周密...

BZOJ1052 BZOJ3760 覆蓋問題

原題位址 先說自己的逗比方法 二分答案,把所有點用乙個最小的矩形 框 起來,易證矩形的其中乙個端點是最優解中正方形的乙個端點,然後列舉四個端點後遞迴處理,差不多了 然後 olz黃學長的o n 做法 ac code include include include using namespace std...