G 血壓遊戲 樹中同一高度點同時向根走,lca

2022-05-01 11:06:13 字數 1552 閱讀 7304

題:

題意:給定n個點的樹,每個節點有權值,每個節點的權值每時刻都會向上移動乙個高度,當節點的權值大於1時,這個節點就會在此節點上權值減少一,直至移動到樹根,把最後的權值加到答案裡去,最後問這個答案總和是多少?

分析:我們知道,不同高度在向根跑的過程中權值的合併(路徑合併),權值減少的過程是互不影響的,這就提示我們可以把同一高度的節點劃分開來,下面對於同一高度的一組來分析;

其中最複雜的情況就是路徑的合併,每條路徑的合併肯定就是在倆倆的lca合併或是倆倆的lca的lca合併或。。。,我們就想辦法把這一組的lca全部求出來呢?因為求出來後,我們就直接模擬答案就行了;

而有乙個結論就是,同一高度的節點的全部lca,就是以各個節點dfs序為序,排序後相鄰的節點的lca就是這些節點向跟跑會經過的結合點,從這可以看出,所有結合點不會超過這一高度節點數-1;

在處理的時候,我們只需對非0點進行處理,對於倆個相鄰節點x,y到lca中去,中間不會有結合,那麼x到lca的貢獻就是他當前的權值-(x到lca的深度之差),y也同理

#includeusing

namespace

std;

typedef

long

long

ll;#define pb push_back

const

int m=2e5+5

;vector

g[m];

intsz[m],deep[m],dfn[m],cnt,f[m],tp[m],son[m],id[m],fa[m];

ll a[m],val[m];

struct

nodesame[m];

void dfs1(int u,int

ff) }

}void dfs2(int u,int

top)

}int lca(int x,int

y)

return deep[x]>deep[y]?y:x;

}int find(int

x)bool cmp1(int x,int

y)bool

cmp2(node x,node y)

intmain()

dfs1(rt,0);

dfs2(rt,rt);

int m=0

;

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

sort(id+1,id+1+m,cmp1);

ll ans=0

;

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

int tot=0

;

for(int i=fir;i)

sort(same+1,same+1+tot,cmp2);

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

ans+=max(1ll,val[same[tot].p]-deep[same[tot].p]);

fir=sec;

}printf(

"%lld

",ans);

return0;

}

view code

血壓遊戲 科大訊飛杯G題 虛樹

一開始的時候,我往長鏈剖分上去寫,但是寫不好,最後寫成了當只有一條鏈的時候是 然後,開始想別的想法了,於是想 到了虛樹的做法。因為,我們可以發現,乙個點,向上影響的時候,只有同等深度的才會同時起作用,只要不是同等深度的時候,那麼他們的時間就會是錯開的,所以,我們可以對深度來進行處理。只有發生這種情況...

牛客 科大訊飛杯 G題血壓遊戲(虛樹 dp)

題意很好理解。而且很容易發現樹中同一深度的松鼠才會打架。預處理出節點的深度和dfs序,然後列舉樹的深度,同一深度的所有節點和根節點s去建虛樹,每建好一次就從根節點s出發跑一次樹型dp dp的轉移方程比較好想,設當前節點為x,si為x的子樹,則dp x max 1,dp si depth si dep...

三 樹 中 4 是否同一棵二叉搜尋樹

給定乙個插入序列就可以唯一確定一棵二叉搜尋樹。然而,一棵給定的二叉搜尋樹卻可以由多種不同的插入序列得到。例如分別按照序列和插入初始為空的二叉搜尋樹,都得到一樣的結果。於是對於輸入的各種插入序列,你需要判斷它們是否能生成一樣的二叉搜尋樹。輸入格式 輸入包含若干組測試資料。每組資料的第1行給出兩個正整數...