原題鏈結
給定乙個長度為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...