傳送門
感覺非常不好寫,我果然討厭資料結構
預處理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。輸出描述 對...