題:
題意:給定n個點的樹,每個節點有權值,每個節點的權值每時刻都會向上移動乙個高度,當節點的權值大於1時,這個節點就會在此節點上權值減少一,直至移動到樹根,把最後的權值加到答案裡去,最後問這個答案總和是多少?
分析:我們知道,不同高度在向根跑的過程中權值的合併(路徑合併),權值減少的過程是互不影響的,這就提示我們可以把同一高度的節點劃分開來,下面對於同一高度的一組來分析;
其中最複雜的情況就是路徑的合併,每條路徑的合併肯定就是在倆倆的lca合併或是倆倆的lca的lca合併或。。。,我們就想辦法把這一組的lca全部求出來呢?因為求出來後,我們就直接模擬答案就行了;
而有乙個結論就是,同一高度的節點的全部lca,就是以各個節點dfs序為序,排序後相鄰的節點的lca就是這些節點向跟跑會經過的結合點,從這可以看出,所有結合點不會超過這一高度節點數-1;
在處理的時候,我們只需對非0點進行處理,對於倆個相鄰節點x,y到lca中去,中間不會有結合,那麼x到lca的貢獻就是他當前的權值-(x到lca的深度之差),y也同理
#includeusingview codenamespace
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;
}
血壓遊戲 科大訊飛杯G題 虛樹
一開始的時候,我往長鏈剖分上去寫,但是寫不好,最後寫成了當只有一條鏈的時候是 然後,開始想別的想法了,於是想 到了虛樹的做法。因為,我們可以發現,乙個點,向上影響的時候,只有同等深度的才會同時起作用,只要不是同等深度的時候,那麼他們的時間就會是錯開的,所以,我們可以對深度來進行處理。只有發生這種情況...
牛客 科大訊飛杯 G題血壓遊戲(虛樹 dp)
題意很好理解。而且很容易發現樹中同一深度的松鼠才會打架。預處理出節點的深度和dfs序,然後列舉樹的深度,同一深度的所有節點和根節點s去建虛樹,每建好一次就從根節點s出發跑一次樹型dp dp的轉移方程比較好想,設當前節點為x,si為x的子樹,則dp x max 1,dp si depth si dep...
三 樹 中 4 是否同一棵二叉搜尋樹
給定乙個插入序列就可以唯一確定一棵二叉搜尋樹。然而,一棵給定的二叉搜尋樹卻可以由多種不同的插入序列得到。例如分別按照序列和插入初始為空的二叉搜尋樹,都得到一樣的結果。於是對於輸入的各種插入序列,你需要判斷它們是否能生成一樣的二叉搜尋樹。輸入格式 輸入包含若干組測試資料。每組資料的第1行給出兩個正整數...