CQOI2015 任務查詢系統題解

2021-09-01 18:35:55 字數 2035 閱讀 4507

題目:

萌新做的第一道主席樹非模板題,emmm說實話搞得我頭皮發麻,想了乙個下午,最後還是去看了某神犇的題解,但是並沒有看懂,似乎用了樹套樹(主席樹套樹狀陣列,複雜度o(nlog2n))。最後沒辦法,自己瞎搞居然搞出來乙個o(nlog2n),瞬間感覺自己很厲害有木有,雖然我不會別人那些高階演算法,但至少我的程式還比較優秀?

不多說廢話,這道題給出一些區間和其對應的權值,要求某個點時包含這個點的區間中前k小的區間權值和。前k小?果斷主席樹。前k小的權值?簡單,按照權值離散化後建樹就行了。

然後,我三下五除二敲完板子,然後懵了:一般的主席樹都是單點修改,這個區間修改讓我很是難受。其實也不麻煩,參考樹狀陣列的單點修改和區間修改的區別,我們差分就可以實現了:即:對於乙個區間,我們把它拆成兩個區間 , 。那麼對應到權值線段樹上,就是在l時將權值為val的點+1,在r+1是將權值為val的點-1。那麼,這時候,我們可以發現問題只剩下怎麼查詢x時的線段樹了。

很簡單,將時間離散化,利用主席樹支援訪問歷史操作的性質,預處理在每乙個l ,r +1,樹上的操作,最後查詢時,只需要二分找到x在修改操作中的位置,就可以得到當時每種權值出現次數了,然後套板子。

一切都顯得這樣美好,但當你信心滿滿提交時,才發現事情沒這麼簡單。原來,在查詢時,即使你分到了最小的區間即l == r是依然可以存在區間中權值個數大於k的情況,但如果沒特判直接返回,那就gg了。所以我們在最後 l == r時,將當前和值除以個數再乘k,就ok了。附**(時間複雜度o(nlog2n)):

#include using namespace std;

typedef long long ll;

const int maxn = 200010;

inline char get_char()

}return *p1++;

}inline ll read()

return res;

}struct data

t[maxn * 2];

bool cmp(data a , data b)

ll n , m , sz , tot , sz2;

ll l[maxn] , r[maxn] , rk[maxn] , rt[20 * maxn] , ls[maxn * 20] , rs[maxn * 20] , cnt[20 * maxn];

ll num[maxn] , tp[maxn] , sum[20 * maxn];

void build(ll& id , ll l , ll r)

ll mid = (l + r) >> 1;

build(ls[id] , l , mid);

build(rs[id] , mid + 1 , r);

}void update(ll& id , ll l , ll r , ll last , ll pos , ll val)

ll mid = (l + r) >> 1;

if (pos <= mid)

else

}ll query(ll s , ll l , ll r , ll k)

else if (l == r)

ll mid = (l + r) >> 1;

if (cnt[ls[s]] >= k)

else

}int main()

sort(tp + 1 , tp + n + 1);

sz = unique(tp + 1 , tp + n + 1) - tp - 1;

build(rt[0] , 1 , sz);

for (ll i = 1; i <= n; i++)

sort(t + 1 , t + top + 1 , cmp);

for (ll i = 1; i <= top; i++)

ll lastans = 1;

for (ll i = 1; i <= m; i++)

else

}lastans = query(rt[pos - 1] , 1 , sz , k);

printf("%lld\n" , lastans);

}return 0;

}

CQOI2015 任務查詢系統

因為對於任務來說,對一段區間是有用的,於是我們可以用差分來表示區間,然後主席樹維護字首區間和即可。然後因為我們是求和,我們同時主席樹也要維護區間的數字個數,因為求k小和。但是有可能當前區間的有a個相同的數字,我們求b個和,然後bac pragma gcc optimize 2 include def...

CQOI2015 任務查詢系統

主席樹維護k大,考慮到利用主席樹字首和的性質。把每個任務拆分成權值為1的進入操作,和權值為 1的退出操作 注意因為是閉區間,所以右邊的位置加進去的時候需要 1 應該是個動態開點的權值線段樹一樣的東西吧 維護v,表示該節點維護的任務數量是多少。sum表示該節點維護的任務總和是多少。輸出k大的時候 因為...

CQOI 2015 任務查詢系統

給定 m 個任務 l,r,p 其中 l,r 代表這個任務將於時間 l,r 內進行,而 p 代表的是這個任務的優先順序 有 n 個詢問 x,k 每次詢問在時間點 x 進行的所有任務按優先順序從小到大排序,前 k 個任務的優先順序之和 求前 k 個數的和,我們想到主席樹 區間覆蓋問題,我們想到差分 眾所...