牛客練習賽9 E 子串 轉移 掃瞄線 樹狀陣列

2021-10-25 16:04:03 字數 2068 閱讀 2362

傳送門

感覺非常不好寫,我果然討厭資料結構

預處理l[i

]l[i]

l[i]

表示左邊第乙個大於i

ii的下標加一

預處理r[i

]r[i]

r[i]

表示右邊第乙個小於i

ii的下標減一

轉移方程是

for

(int i=

1;i<=n;i++

)//作為右端點時,找左邊第乙個比i大的數字

pos

[i

]pos[i]

pos[i]

表示數字i

ii出現的下標

那麼當點i

ii作為fai

rfair

fair

區間的左端點時,右端點必須在區間[i,

ri

][i,r_i]

[i,ri​

]才能滿足i

ii為最小值

但是還需要包括i

ii,所以真實的區間是[po

si,r

i]

[pos_i,r_i]

[posi​

,ri​

] 當點i

ii作為fai

rfair

fair

區間的右端點時,左端點必須在區間[li

,i

][l_i,i]

[li​,i

]才能滿足i

ii為最大值

但是還需要包括i

ii,所以真實的區間是[li

,pos

i]

[l_i,pos_i]

[li​,p

osi​

] 那麼我們把每個點作為fai

rfair

fair

區間左端點時,滿足條件的右端點範圍[l,

r]

[l,r]

[l,r

]拆分一下

( l,

i,1)

(l,i,1)

(l,i,1

)和(r+1

,i,−

1)

(r+1,i,-1)

(r+1,i

,−1)

也就是利用掃瞄線的性質,列舉每乙個點作為右端點,動態加入滿足條件的左端點

這樣當我們計算右端點時,左端點一定是滿足要求的

從1

11到n

nn列舉右端點即可

#include

using

namespace std;

#define int long long

const

int maxn =

1e6+10;

int n,p[maxn]

,pos[maxn]

,sum[maxn]

,l[maxn]

,r[maxn]

,top;

struct node

}line[maxn<<1]

;int

lowbit

(int x)

void

add(

int x,

int val)

intask

(int x,

int ans=0)

signed

main()

for(

int i=n;i>=

1;i--

)//作為左端點時,找右邊第乙個比i小的數字

for(

int i=

1;i<=n;i++);

line[

++top]=;

}}sort

( line+

1,line+

1+top )

;int ans =

0,now =1;

for(

int i=

1;i<=n;i++

)//列舉每個點作為右端點

cout << ans;

}

牛客練習賽69E 子串 樹狀陣列

給出乙個n nn的排列,求有多少個區間 l,r l,r l,r 使得最大值是r rr,最小值是lll。首先對於乙個位置的值作為左端點和右端點都有一段合法區間 到左邊第乙個比他小的和右邊第乙個比他大的,當右端點時同理 可以用樹狀陣列預處理每個的合法區間 然後對於兩個點各作為左右端點需要滿足左端點在右端...

牛客練習賽69 E 字串 雜湊

給出乙個長度為n排列p 規定乙個區間 l,r l r 是 fair 的,當且僅當區間中最小值等於 l 並且最大值等於 r 求 fair 區間的個數 我不會正解 首先把每乙個i值對映成 base i 遍歷一邊全排列 然後每次加上base a i 減去base i 求貢獻,如果 l,r 滿足條件,那麼這...

牛客練習賽51(B題 子串查詢)

題目描述 給出乙個長度為n的字串s和q個查詢。對於每乙個查詢,會輸入乙個字串t,你需要判斷這個字串t是不是s的子串。子串的定義就是存在任意下標a輸入描述 第一行兩個數n,q。1 n,q 1e5。第二行乙個長度為n的字串s,所有字元都為小寫拉丁字元。接下來q行每行乙個字串t。1 t 50。輸出描述 對...