因為noip2018考了這乙個東西,所以不得不學。
我們以這一題為例題來引入今天的學習:【模板】動態dp
我們顯然可以用樹形dp去做,倒不如我們先把方程列出來。
這兩條公式挺顯然的吧。
假設我們現在無聊,往樹鏈剖分的角度去考慮。
那麼我們設乙個陣列g,表示的是從非重兒子轉移來的狀態,跟f陣列的轉移方程類似。
我們可以把上面兩條公式改寫成什麼呢?
這兩條也是挺顯然的吧。
那麼這個東西有什麼用呢?
對於一條重鏈來說,g肯定是不會改變的,但是f是可能改變的。
我們試著去構造乙個轉移矩陣:
我們定義這個乘法的含義是
然後化簡出來出來就是上面那兩條公式。
這個東西有什麼用?
容易發現
這個也是挺顯然的吧,因為每乙個點存的都是非重兒子的答案,那麼多個非重兒子的答案合併就變成了該子樹的答案。
那麼我們把乙個點的權值變成了所在重鏈的乘積。(注意,上面的乘積和pi,都是新定義的*)
假設我們要改x點的權值,那麼x所在的矩陣要修改吧,那麼就變成了改點。
我們還可以求出不在這條重鏈上的第乙個祖先,那麼這個祖先的矩陣也要改,具體怎麼改,可以通過原來x點所在重鏈的top的子樹的答案的變化量來修改。
一直這樣往上跳,一共會改log個節點,因為要訪問區間連乘積,所以用線段樹維護,時間複雜度就是:
雖然樹鏈剖分的常數不大,但是這個log平方的演算法已經夠卡常的了。
我還沒有學會全域性平衡二叉樹。
#include#include#include#include#define lc (now<<1)
#define rc ((now<<1)|1)
using namespace std;
int n,m;
int w[100010];
struct edges[200010];
struct matrix
return q;
}}tr[300010];
int first[100010],len=0;
int tot[100010],son[100010];
int image[100010],fact[100010],last[100010],fa[100010],top[100010];
int f[100010][2],g[100010][2];
void ins(int x,int y);first[x]=len;
}void dfs_1(int x)
}void dfs_2(int x,int tp)
for(int i=first[x];i!=0;i=s[i].next)
}void tr_dp(int x)
}void update(int now,int l,int r,int x)
int mid=(l+r)/2;
if(x<=mid) update(lc,l,mid,x);
else update(rc,mid+1,r,x);
tr[now]=tr[lc]*tr[rc];
}matrix query(int now,int x,int y,int l,int r)
void build(int now,int l,int r)
int mid=(l+r)/2;
build(lc,l,mid);build(rc,mid+1,r);
tr[now]=tr[lc]*tr[rc];
}void change(int x,int y)
}int main()
len=0;
dfs_1(1);dfs_2(1,1);
tr_dp(1);
build(1,1,n);
for(int i=1;i<=m;i++)
}
第二十九節,裝飾器
裝飾器簡介 裝飾器,用於裝飾某個函式,或者方法,或者類 裝飾可以用於某個函式或者方法或者類在執行之前或者執行後做某些操作,也可以理解為,為某個函式或者方法或者類新增功能 好處 是不用改變原來的函式,就可以給原來的函式新增功能 方法 1,定義乙個函式,裡面傳乙個值用於接收被裝飾函式的名稱 叫做裝飾器函...
第二十九節,裝飾器
第二十九節,裝飾器 裝飾器簡介 裝飾器,用於裝飾某個函式,或者方法,或者類 裝飾可以用於某個函式或者方法或者類在執行之前或者執行後做某些操作,也可以理解為,為某個函式或者方法或者類新增功能 好處 是不用改變原來的函式,就可以給原來的函式新增功能 方法 1,定義乙個函式,裡面傳乙個值用於接收被裝飾函式...
2018 9 13第二十九次筆記
一.暫存器 1.暫存器是硬體,它其實就是乙個開關,當用編寫好的 去操作外設時,軟體是實現不了外設的,最終實現功能的還是靠硬體,暫存器就是這樣實現軟體功能的硬體。暫存器是cpu的硬體設計者制定的。2.使用軟體程式設計控制某乙個硬體,其實就是程式設計讀寫該硬體的暫存器。3.暫存器分為通用暫存器和特殊暫存...