題解 CQOI2015任務查詢系統

2022-02-27 14:04:15 字數 1755 閱讀 4334

主席樹,操作上面基本上是一樣的。每乙個時間節點一棵樹,乙個樹上的每個節點代表乙個優先順序的節點。把開始和結束時間點離散,在每一棵樹上進行修改。注意因為乙個時間節點可能會有多個修改,但我們要保證都在同一棵樹上,所以我採取了讓每個節點額外儲存所屬於的樹的乙個資訊。當更新到乙個節點的時候,如果屬於建立好的新樹,那麼就修改;不屬於,則重新建鏈。

但這題有乙個地方需要注意,就是所求的個數有可能小於乙個葉子結點中儲存的任務個數,這時我們就要返回k * num。

//

luogu-judger-enable-o2

#include using

namespace

std;

#define int long long

#define maxn 1500000

int n, m, timer, tot, cnt, sum, pre = 1

, root[maxn], ti[maxn];

map

map;

bool

vis[maxn];

struct

node

upd[maxn * 2

];struct

tree

t[maxn * 5

];struct

project

p[maxn];

bool

cmp(project a, project b)

bool

cmp2(node a, node b)

intread()

while(c >= '

0' && c <= '

9') x = x * 10 + c - '

0', c =getchar();

return x *k;

}void update(int &now, int bf, int x, int num, int l, int r, int

root)

int mid = (l + r) >> 1

;

if(x <=mid) update(t[now].lson, t[bf].lson, x, num, l, mid, root);

else update(t[now].rson, t[bf].rson, x, num, mid + 1

, r, root);

t[now].cal = t[t[now].lson].cal +t[t[now].rson].cal;

}int query(int now, int l, int r, int

k)signed main()

; upd[++ cnt] = (node) ;

}sort(p + 1, p + 1 +m, cmp);

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

if(p[i].p != p[i - 1].p) map[p[i].p] = ++tot;

sort(upd + 1, upd + 1 +cnt, cmp2);

for(int i = 1; i <= cnt; i ++)

int t =ti[upd[i].t];

update(root[t], root[t - 1], map[abs(upd[i].num)], upd[i].num, 1

, tot, t);

vis[t] = true

; }

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

return0;

}

CQOI2015 任務查詢系統題解

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

CQOI2015 任務查詢系統

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

CQOI2015 任務查詢系統

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