1. 程式人生 > 遊戲資訊 >Doinb透露LPL夏季賽很緊湊,為備戰亞運會每天四個BO3

Doinb透露LPL夏季賽很緊湊,為備戰亞運會每天四個BO3

可持久化線段樹 2

題意:

給一陣列 多次詢問一個區間 求該區間第k大的數 n和q都可以到達2e5

思路:

每次查詢 直接暴力找第k大的數肯定會超時 然而如果用普通線段樹 因為每次查詢的k不一樣就要維護很多棵樹會爆空間 所以要用主席樹

每次更新一個數就新增一個根節點 只更新維護的區間中包含當前數的節點 其餘的點延續上一個根節點維護的線段樹 

利用字首和思想 :

l r區段的數的個數就是sum[rt[r]] - sum[rt[l - 1]] 

#include<iostream>
#include<algorithm>
#include<string> 
#include
<set> #include<map> #include<cstdio> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<unordered_map> #include<iomanip> #define ll long long #define ull unsigned long long #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) #define
m_p make_pair #define pi acos(-1) using namespace std; const int N = 3e5 + 5; const double eps = 1e-4; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; inline ll qpow(ll x, ll y, ll M){ll ans=1;while(y){if(y&1)ans=ans*x%M;x=x*x%M;y=y>>1;}return ans;} inline ll gcd(ll x, ll y){
return y?gcd(y,x%y):x;} int n; ll a[N], b[N], len, p, m; ll sum[N << 5], lc[N <<5], rc[N << 5], rt[N << 5], sz; string s; //建樹 sz記錄 節點個數 rt陣列 記錄每個根節點的編號 void build(ll &rt, ll l, ll r){ rt = ++sz; sum[rt] = 0; if(l == r) return; ll mid = (l + r) >> 1; build(lc[rt], l, mid); build(rc[rt], mid + 1, r); } //更新 ll update(ll o, ll l, ll r){ //新建一個點 ll oo = ++sz; //延續前一個根節點的資訊 lc[oo] = lc[o]; rc[oo] = rc[o]; sum[oo] = sum[o] + 1; if(l == r) return oo; ll mid = (l + r) / 2; if(mid >= p) lc[oo] = update(lc[oo], l, mid); else rc[oo] = update(rc[oo], mid + 1, r); return oo;//用於遞迴返回新建點 使更新關係 } //詢問 ll query(ll u, ll v, ll l, ll r, ll k){ ll mid = (l + r) / 2; //左區間的個數 ll x = sum[lc[v]] - sum[lc[u]]; if(l == r) return l; //多了再往左找 if(x >= k) return query(lc[u], lc[v], l, mid, k); else return query(rc[u], rc[v], mid + 1, r, k - x); //少了往右找 } void solve() { cin >> n >> m; for(int i = 1; i <= n; i++){ cin >> a[i]; b[i] = a[i]; } //離散化 去重 sort(b + 1, b + 1 + n); len = unique(b + 1, b + 1 + n) - b - 1; //建空樹 也可以不建 build(rt[0], 1, len); for(int i = 1; i <= n; i++){ //二分查詢a[i]再b陣列中的位置 p = lower_bound(b + 1, b + 1 + len, a[i]) - b; rt[i] = update(rt[i - 1], 1, len); } ll l, r, k; while(m--){ cin >> l >> r >> k; ll ans = b[query(rt[l - 1], rt[r], 1, len, k)]; cout << ans << "\n"; } } signed main() { IOS; //init(); ll t = 1; //cin>>t; while(t--) solve(); return 0; }