洛谷P3261 JLOI2015 城池攻占

2022-05-23 22:18:11 字數 1414 閱讀 5972

題目大意:有$n$個點的樹,第$i$個節點有乙個權值$h_i$,$m$個騎士,第$i$個騎士攻擊力為$v_i$,乙個騎士可以把從它開始的連續的父親中比它小的節點攻破,攻破乙個節點可以把攻擊力加或乘乙個數(乘的數大於$0$)(每個騎士獨立),問每個騎士可以攻破多少個點,每個點會阻擋住多少個騎士。

題解:可以把所有騎士一起考慮,建乙個小根堆,存可以攻打到這個點的騎士,每個若堆頂小於該點,就彈出,寫乙個打標記的可並堆就行了。

卡點:快讀中讀入$long\;long$的部分返回值變成$int$

c++ code:

#include #include #include namespace __io 

long long x;

inline long long readll() }}

using __io::r::read;

using __io::r::readll;

#define maxn 300010

int head[maxn], cnt;

struct edge e[maxn << 1];

inline void addedge(int a, int b) ; head[a] = cnt;

}namespace heap

inline void add(int rt, long long num)

inline void pushdown(int rt)

if (__a)

} int __merge(int x, int y)

int merge(int x, int y)

int insert(int rt, long long val, int pos)

int pop(int rt)

}int n, m;

int a[maxn], c[maxn], dead[maxn], num[maxn];

int rt[maxn], dep[maxn];

long long w[maxn], v[maxn];

void dfs(int u)

while (rt[u] && heap::v[rt[u]] < w[u])

if (rt[u])

}int main()

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

dfs(dep[1] = 1);

for (int i = 1; i <= n; i++) printf("%d\n", num[i]);

for (int i = 1; i <= m; i++) printf("%d\n", dep[c[i]] - dep[dead[i]]);

return 0;

}

洛谷P3261 JLOI2015 城池攻占

不得不說,這道題目是真的難,真不愧它的 省選 noi 的紫色大火題!花了我晚自習前半節課看題解,寫 又花了我半節晚自習調 真的心態 基本上改得和題解完全一樣了我才過了這道題!真的煩。沒事,那接下來我來完全把這道題搞透。part 1 理解題目 至少我一開始不知道為什麼要用左偏樹,甚至我看題解一開始也都...

洛谷P3261 JLOI2015 城池攻占

思路分析 由於這道題的資料範圍是n,m 3e5,所以我們直接輸入乙個模擬乙個是會超時的,但是我們可以在輸入所有的士兵之後把同在乙個節點的士兵一起處理,我們可以考慮建乙個堆,從深度最大的節點開始,維護乙個節點內的士兵的最小戰鬥力值,如果戰鬥力最小的士兵都能存活下來,那麼在堆中的其他士兵一定可以活下來,...

P3261 JLOI2015 城池攻占

p3261 jloi2015 城池攻占 乍一看,平衡樹?其實左偏樹更好做啦 qwq 每個節點都來棵左偏樹維護最小值,dfs 往上時合併一下,要是攻不下了就把根節點刪掉,直到能攻下,對了,攻下後值會變化怎麼辦?lazy 標記一下,和線段樹同理 include includeusing namespac...