題面
考慮把每一對點的路徑放到其lca上考慮,為敘述方便,記so
nxs on
x為當前點兒子中子樹包含
x x
的那乙個。設fi
,s' role="presentation" style="position: relative;">fi,
sfi,
s表示在子樹
i i
中,只考慮
s' role="presentation" style="position: relative;">s
s那些兒子的最大值,在設gi
,xg i,
x表示so
nxs on
x中
i i
到x' role="presentation" style="position: relative;">x
x的鏈強制不能選的最大值。
然後對於每個
i i
,g' role="presentation" style="position: relative;">g
g顯然能o(
n)o (n
)求出,就是fx
,ful
lx+∑
j∈x→
ifj,
full
j−so
nxf x,
full
x+∑j
∈x→i
fj,f
ullj
−son
x所以對於路徑(x
,y) (x,
y)
滿足lc
a(x,
y)=i
l ca
(x,y
)=
i,就有轉移: fi
,s=max
(137)
(137)fi
,s
=max
複雜度o(
n2+m
∗2de
gi) o(n
2+m∗
2deg
i)
,已經可以過了,好像還可以記個mx
x,y mxx
,y
表示選的路徑端點分別在x,
y x,
y兩個兒子中的最大值,然後就可以優化到o(
n2+n
∗2de
gi) o(n
2+n∗
2deg
i)
,不過我沒寫。
**:
#include
#include
#include
#include
#include
#define n 1010
#define pii pair
#define mp make_pair
#define pb push_back
#define fs first
#define sc second
#define chkmax(x,y) x=max(x,y)
using namespace std;
int n,m,f[n][1030],g[n],fa[13][n],dep[n];
bool son[n][n];
vectorq[n];
vector e[n];
intread()
void dfs1(int v)
else swap(e[v][i],e[v][0]);
}int lca(int
x,int
y)void calg(int v,int add)
for(int i=0;ifor(int
s=0;s
<=t;s++)
if((!sx||((s>>(sx-1))&1))&&((!sy||(s>>(sy-1))&1)))
chkmax(f[v][s],f[v][s-(sx?(1
<<(sx-1)):0)-(sy?(1
<<(sy-1)):0)]+g[q[v][i].fs]+g[q[v][i].sc]+1);
}for(int i=1;i1
<<(i-1))]);
g[v]=f[v][t];
}int main()
e[1].pb(0);
dfs1(1);
for(int k=1;(1
fa[k][i]=fa[k-1][fa[k-1][i]];
m=read();
for(int i=1;i<=m;i++)
dfs2(1);
printf("%d\n",f[1][(1
<<(e[1].size()-1))-1]);
return
0;}
雅禮集訓 2018 Day4 Magic
傳送門本部分 於 這位大佬 題中要求本質不同的序列數量,不太好搞。我們考慮給相同顏色的牌加上編號,這樣所有牌都不相同。那麼如果我們求出了答案,只需要將答案除以 prod a i 就好了。恰好有 k 對 不能直接求,考慮容斥,如果我們求出了 g x 表示至少有 x 對的方案數,那麼答案即為 sum l...
雅禮集訓 2018 Day7 A 題解
題意 雅禮集訓 2018 day7 a 題解 線段樹處理。考慮只有一種與的操作。顯然當乙個區間的或和與上將要與的數還是原數時就沒必要遞迴計算了,剪枝剪掉。當一段區間與和與上將要與的數等於這段區間或和與上將要與的數時,更新後這段區間的最小值位置還是更新前的位置。由於一次操作至少將數的乙個二進位制改變,...
2018雅禮集訓1 16 方陣
給出乙個 n m 大小的矩形,每個位置可以填上 1,c 中的任意乙個數,要求填好後任意兩行互不等價且任意兩列互不等價,兩行或兩列等價當且僅當對應位置完全相同,求方案數 n,m le 5000 確實是一道神仙題。對這種行列都有限制的題我們可以先只考慮一邊。我們先只考慮讓行之間互不等價,乙個 n行m列 ...