小銘銘最近獲得了一副新的桌遊,遊戲中需要用 m 個騎士攻占 n 個城池。
這 n 個城池用 1 到 n 的整數表示。除 1 號城池外,城池 i 會受到另一座城池 fi 的管轄,
其中 fi < i。也就是說,所有城池構成了一棵有根樹。這 m 個騎士用 1 到 m 的整數表示,其中第 i 個騎士的初始戰鬥力為 si,第乙個攻擊的城池為 ci。
每個城池有乙個防禦值 hi,如果乙個騎士的戰鬥力大於等於城池的生命值,那麼騎士就可以占領這座城池;否則占領失敗,騎士將在這座城池犧牲。占領乙個城池以後,騎士的戰鬥力將發生變化,然後繼續攻擊管轄這座城池的城池,直到占領 1 號城池,或犧牲為止。
除 1 號城池外,每個城池 i 會給出乙個戰鬥力變化引數 ai;vi。若 ai =0,攻占城池 i 以後騎士戰鬥力會增加 vi;若 ai =1,攻占城池 i 以後,戰鬥力會乘以 vi。注意每個騎士是單獨計算的。也就是說乙個騎士攻擊一座城池,不管結果如何,均不會影響其他騎士攻擊這座城池的結果。
現在的問題是,對於每個城池,輸出有多少個騎士在這裡犧牲;對於每個騎士,輸出他攻占的城池數量。
顯然可並堆可以維護,從底往上合併,合併的時候打個標記即可。
code:
#include
#include
#include
#include
#define ll long long
using namespace std;
struct nodea[300010];int len=0,last[300010];
struct trnodetr[300010];
void ins(int
x,int
y)int n,m,op[300010],c[300010],root[300010],ans[300010],num[300010],dep[300010];
ll h[300010],v[300010];
void pushdown(int
x)int merge(int
x,int
y)void dfs(int
x,int fa)
while(root[x]&&tr[root[x]].cx]) ans[root[x]]=x,num[x]++,pushdown(root[x]),root[x]=merge(tr[root[x]].lc,tr[root[x]].rc);
}int main()
for(int i=1;i<=m;i++)
dfs(1,0);
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[ans[i]]);
}
bzoj 4003 JLOI2015 城池攻占
小銘銘最近獲得了一副新的桌遊,遊戲中需要用 m 個騎士攻占 n 個城池。這 n 個城池用 1 到 n 的整數表示。除 1 號城池外,城池 i 會受到另一座城池 fi 的管轄,其中 fi 第 1 行包含兩個正整數 n m,表示城池的數量和騎士的數量。第 2 行包含 n 個整數,其中第 i 個數為 hi...
BZOJ4003 JLOI2015 城池攻占
time limit 20 sec memory limit 128 mb submit 1356 solved 510 submit status discuss 小銘銘最近獲得了一副新的桌遊,遊戲中需要用 m 個騎士攻占 n 個城池。這 n 個城池用 1 到 n 的整數表示。除 1 號城池外,城...
BZOJ4003 JLOI2015 城池攻占
左偏樹裸題 合併 lazytag即可 每個點合併兒子然後彈出所有然後每個騎士直接dep x dep y 掛了的節點和初始節點的深度差即可 樣例太水了注意要判每個節點萬一騎士掛完了是空的qaq love and freedom.include include include include defin...