bzoj 4003 JLOI2015 城池攻占

2021-08-15 23:41:41 字數 1385 閱讀 1322

小銘銘最近獲得了一副新的桌遊,遊戲中需要用 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...