巴蜀 士兵訓練

2021-08-24 20:36:35 字數 3367 閱讀 9857

在 c 國中有 n 位士兵,除士兵 1 外,每位士兵 i 均有且僅有一位士兵j(

jj (j

作為他的直屬教官。士兵 i 被他的直屬教官 j 以及所有能管轄 j 的士兵所管轄。每位士兵也看做能管轄自己。

每位士兵均有兩個屬性值:戰鬥力bi

b

i與領導力 li

l i。

現在 c 國要舉行 q 次閱兵,每次閱兵會指定一位士兵 s 做總指揮,士兵 s需要訓練自己所管轄的所有士兵,並以最好的精神面貌迎接閱兵式。

士兵 s 每次閱兵訓練時有一次機會(只能使用一次或不使用),可以邀請一位不受他管轄的士兵 i 來指導一位他所管轄的士兵 j,並會使得士兵 j 的戰鬥力由bj

b

j提公升為bj

+li bj+

li

,這次提公升僅對當次閱兵有效。

士兵 s 訓練出的士兵隊伍所能展現出的精神力 p 為:ma

x max

,i、j 被s管轄

現在 c 國主席想知道,每次閱兵的隊伍所能展現出的精神力 p 最大能是多少?請你幫助他。

第一行兩個數 n,q 表示士兵數以及閱兵次數。

接下來一行 n-1 個整數,第 i 個整數表示士兵 i+1 的直屬教官。

接下來 n 行每行兩個整數 bi

,li bi,

li

描述一位士兵的屬性。

接下來 q 行每行乙個整數si

s

i,表示這次閱兵的總指揮。

對於每次閱兵輸出一行乙個整數,表示閱兵隊伍能展現出的最大精神力 p。

5 2

1 1 2 2

2 1

1 5

4 2

2 3

3 1 1 2

3 37 3

1 1 2 2 3 3

3 0

1 3

5 2

2 0

4 1

3 1

2 2

1 2 35

3 40817 orz

簡化題意,即:允許將s的子樹中的乙個點加上某一權值(也可以不加),求不同方法更新後的子樹嚴格次大值的最大值。

我們記錄子樹中原來的戰鬥力最大值、次大值、第三大值分別為b0

,b1,

b2b 0,

b1,b

2,子樹外的領導力最大值、次大值為l0

,l1 l0,

l1

。要求b0

≥b1,

b1>b2

,l0>l1

b 0≥

b1,b

1>b2

,l

0>l1

當b1+l0≠

b0b 1+

l0≠b

0時,顯然將b1

b

1加上l0

l

0是最優的 當b

1+l0

=b0 b1+

l0=b

0時,顯然不能這樣加(否則mod出來是0)。於是就有兩種可能的答案:b1

+l1 b1+

l1

和l0+b

2 l0+

b2

。對兩種答案取max即可

子樹問題,可用dfs序化為序列區間問題。可以用線段樹維護子樹戰鬥力極值,用字首字尾維護不在子樹的領導力極值。

#include 

#include

using namespace std

;struct dtmaxn[1110000];

struct nodefrl[222222],bel[222222];

int b[222222],l[222222];

int newid[222222];

node mex(node a,node b)

dt max(dt a,dt b)

else

return ans;

}void init(int now,int l,int r)

int mid=l+r >>1,ls=now<<1,rs=(now<<1)|1

; init(ls,l,mid);

init(rs,mid+1,r);

maxn[now]=max(maxn[ls],maxn[rs]);

}dt got(int now,int l,int r,int x,int y)

; if(x

<=mid)ans=max(ans,got(ls,l,mid,x,y));

if(y>mid)ans=max(ans,got(rs,mid+1,r,x,y));

return ans;

}int nn[222222],las[222222];

int in[222222],out[222222];

int time=0

;void dfs(int x)

int main()

; for(i=1

;i<=n;i++)

frl[i]=mex(frl[i-1],(node));

for(i=n;i;--i)

bel[i]=mex(bel[i+1],(node));

while(q--)

}return 0;}

/**/

以上**是本蒟蒻在神志不清的時候打的,實際上根本不用線段樹

dfs一下,合併即可

#include 

#include

using namespace std

;struct dtans[1110000];

struct nodefrl[222222],bel[222222];

int l[222222];

int newid[222222];

node mex(node a,node b)

dt max(dt a,dt b)

else

return ans;

}int nn[222222],las[222222];

int in[222222],out[222222];

int time=0

;void dfs(int x)

out[x]=time;

}int main()

; for(i=1

;i<=n;i++)

frl[i]=mex(frl[i-1],(node));

for(i=n;i;--i)

bel[i]=mex(bel[i+1],(node));

while(q--)

}return 0

;}

士兵佇列訓練

某部隊進行新兵佇列訓練,將新兵從一開始按順序依次編號,並排成一行橫隊,訓練的規則如下 從頭開始一至二報數,凡報到二的出列,剩下的向小序號方向靠攏,再從頭開始進行一至三報數,凡報到三的出列,剩下的向小序號方向靠攏,繼續從頭開始進行一至二報數。以後從頭開始輪流進行一至二報數 一至三報數直到剩下的人數不超...

士兵佇列訓練問題

實驗任務 某部隊進行新兵佇列訓練,將新兵從一開始按順序依次編號,並排成一行橫隊,訓練的 規則如下 從頭開始一至二報數,凡報到二的出列,剩下的向小序號方向靠 攏,再從頭開 始進行一至三報數,凡報到三的出列,剩下的向小序號方向靠攏,繼續從頭開始進行一至二 報數。以後從頭開始輪流進行一至二報數 一至三報 ...

士兵佇列訓練問題

題意 hdoj1276 典型的佇列問題,入門水題 題解 第一次做普通佇列,引用了別人的演算法,優化了一下,題解記錄學到的一點東西 佇列和陣列之類的東西完全不同,和棧一樣,被固定的順序和進出卡的很死,所以在做佇列的題目時,不能像陣列一樣思維 因為是3個人,所以首先按佇列的大小來卡人數,初始化的時候,從...