牛客練習賽73 D離別 線段樹 離線

2021-10-10 18:32:20 字數 1844 閱讀 6024

原題鏈結

給定乙個長度為n的數列,每次詢問乙個區間(l, r),求滿足區間內最大出現次數等於k次的子區間個數

對於子區間問題,我們可以離線處理出所有滿足的區間。比如對所有區間的右邊界進行排序,然後遍歷右邊界,找到符合的左邊界的區間。至於怎麼去找符合條件的左區間,我們可以用乙個佇列來存相同數字的下標,如果剛好出現第k個數字,那麼佇列裡第乙個數字就是左區間的右邊界,如果出現了大於k個數字,那麼佇列裡第乙個數字的下標+1就是滿足條件的左區間的左邊界,那麼在左右邊界之內的都是合法的。區間和自然可以考慮用線段樹維護,時間複雜度在nlog(n).

#include

//#define acm_local

using

namespace std;

typedef

long

long ll;

typedef pair<

int,

int> pii;

const

int n =

3e5+

10, m =

1e5+

10, inf =

0x3f3f3f3f

;const

int mod =

1e9+7;

int n, m, k;

struct segtree

void

push_down

(int u)

}void

build

(int u,

int l,

int r)

ll query

(int u,

int ql,

int qr)

void

update

(int u,

int ql,

int qr,

int v)

push_down

(u);

int mid =

(l[u]

+ r[u]

)>>1;

if(ql <= mid)

update

(lc, ql, qr, v);if

(qr > mid)

update

(rc, ql, qr, v)

;push_up

(u);

}} st;

struct q

}q[n]

;int l[n]

, r[n]

, a[n]

;ll ans[n]

;queue<

int> que[n]

;void

solve()

l[0]

=1;for

(int i =

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

(que[a[i]].

size()

== k)

}sort

(q+1

, q+m+1)

; st.

build(1

,1, n)

;int j =1;

for(

int i =

1; i <= m; i++

) ans[q[i]

.id]

= st.

query(1

, q[i]

.l, q[i]

.r);

}for

(int i =

1; i <= m; i++

)printf

("%lld\n"

, ans[i]);

}signed

main()

牛客練習賽73

傳送門 思路 本題有兩種方法,一是模擬,將所有人的總分算出來後進行排序,只要小a考到第m個人的分數那麼就可以,但資料有坑,減去校測分後得到的可能是負數,即意味著小a只需要考0分即可。二是正解,題目要求找乙個數就可以聯想到二分,對於小數操作就可以放大為整數,就是mid85 p15,然後將資料型別擴充套...

牛客練習賽 資料結構 線段樹

qn姐姐最好了 qn姐姐給你了乙個長度為n的序列還有m次操作讓你玩,1 l r 詢問區間 l,r 內的元素和 2 l r 詢問區間 l,r 內的元素的平方和 3 l r x 將區間 l,r 內的每乙個元素都乘上x 4 l r x 將區間 l,r 內的每乙個元素都加上x 第一行兩個數n,m 接下來一行...

牛客練習賽24 D

名字挺有意思的,排插樹,雖然這是個圖。算dijkstra的模版題,求最短路裡面最長的那條,因為到講台的距離總是取決於最短的那條路,但是又要求離講台最遠,那麼我們通過dijkstra計算出起始點到所有點的最短路然後遍歷找最大值就好。如下 include using namespace std type...