JZOJ6258 省選模擬8 9 轟炸

2021-09-26 04:55:24 字數 3202 閱讀 2884

給你一棵樹和樹上的許多條從後代到祖先的鏈,選擇每條鏈需要一定代價,問覆蓋整棵樹的所有點的最小代價是多少。

n ,m

≤100000

n,m\leq 100000

n,m≤10

0000

(由於時間過於久遠,所以直接說正解算了)

對於這樣的題,顯然有一種暴力的dp做法。

設f i,

jf_

fi,j

​表示i

ii子樹全部被覆蓋,其中伸出來的一條鏈到達深度為j

jj的祖先時的最小代價。

轉移不在此贅述。

然後可以線段樹優化。

有兩種情況:從i

ii子樹伸出來的鏈是最高的;從i

ii伸出來的鏈是最高的。

我們欽定某一條鏈是最高的,不用管是否存在其他的鏈高過它的情況,因為如果有那樣的情況,那麼這個狀態的答案就會被覆蓋掉。

首先記錄一下每個子樹的最優答案之和,記作sum

sumsu

m。枚舉子樹,對於它的所有狀態加上sum

sumsu

m,減去它本身的最優答案。也就是將其它子樹的答案之和給它加上。對於自己,就直接用sum

sumsu

m加上所選擇的鏈的代價。

然後線段樹合併即可。

using

namespace std;

#include

#include

#include

#include

#define n 300010

#define inf 1000000000000000000

int n,m;

struct edge e[n*2]

;int ne;

edge *last[n]

;int dep[n]

;struct edge2 e2[n*2]

;int ne2;

edge2 *last2[n]

;struct node

inline

void

update()

} d[n*30]

,*null;

int cnt;

inline node *

newnode()

);}node *root[n]

;void

change

(node *t,

int l,

int r,

int x,

long

long c)

t->

pushdown()

;int mid=l+r>>1;

if(x<=mid)

change

(t->l==null?t-

>l=

newnode()

:t->l,l,mid,x,c)

;else

change

(t->r==null?t-

>r=

newnode()

:t->r,mid+

1,r,x,c)

; t-

>

update()

;}void

cut(node *t,

int l,

int r,

int en)

else

cut(t-

>r,mid+

1,r,en)

; t-

>

update()

;}node *

merge

(node *a,node *b,

int l,

int r,

long

long plus,

int en)

if(b==null)

return a;

if(l==r)

a->

pushdown()

,b->

pushdown()

;int mid=l+r>>1;

a->l=

merge

(a->l,b-

>l,l,mid,plus,en);if

(mida-

>r=

merge

(a->r,b-

>r,mid+

1,r,plus,en)

;else

a->r=null;

a->

update()

;return a;

}bool

dfs(

int x,

int fa)

node *un=

newnode()

;for

(edge *ei=last[x]

;ei;ei=ei-

>las)

if(ei-

>to!=fa)

un=merge

(un,root[ei-

>to],1

,n,sum-root[ei-

>to]

->mn,x==1?

1:dep[x]-1

);for(edge2 *ei=last2[x]

;ei;ei=ei-

>las)

change

(un,

1,n,dep[ei-

>to]

,ei-

>w+sum)

; root[x]

=un;

return root[x]

->mn>=inf;

}int

main()

; last[u]

=e+ne++

; e[ne]=;

last[v]

=e+ne++;}

for(

int i=

1;i<=m;

++i)

; last2[u]

=e2+ne2++;}

null=d;

*null=;if

(dfs(1

,0))

printf

("-1\n");

else

printf

("%lld\n"

,root[1]

->mn)

;return0;

}

這種樹上dp的東西很多時候都可以揹包啊……

JZOJ6258 省選模擬8 9 轟炸

給你一棵樹和樹上的許多條從後代到祖先的鏈,選擇每條鏈需要一定代價,問覆蓋整棵樹的所有點的最小代價是多少。n,m leq 100000 由於時間過於久遠,所以直接說正解算了 對於這樣的題,顯然有一種暴力的dp做法。設 f 表示 i 子樹全部被覆蓋,其中伸出來的一條鏈到達深度為 j 的祖先時的最小代價。...

JZOJ6257 省選模擬8 9 修路

有一堆點,每個點都有其權值c ic i ci 每次插入邊 u,v u,v u,v u uu和1 11連通,v vv和1 11不連通。最後保證形成一棵樹。每次插入的時候詢問1 11到u uu的路徑上逆序對的個數。然後將1 11到u uu的路徑上的所有節點的權值設為c vc v cv 一看就知道是什麼資...

JZOJ 省選模擬 string

一行乙個整數表示答案。sample input 樣例輸入 3 3sample output 樣例輸出 首先我們忽略重複的字串,定義 n 表示長度為 n 的回文串,或由兩個回文串拼成的字串數量。那麼可以通過列舉第乙個回文串的長度 可以為 0 可以算出f n 但是正如剛才所說,會對如 abaaba 這樣...