給出一棵樹 每個點都有乙個顏色ci 問 從i號點出發到任意乙個點的路徑上本質不同的顏色之和。
\(n\leq 300000\)
光線性掃瞄時不行的 顯然有\(n^2\)的暴力。
考慮樹是一條鏈的時候怎麼做? 可以發現先求出1的答案然後維護換根的過程 記錄每個點顏色的pre 前驅 nex後繼很容易通過分類討論得到答案。
考慮樹的時候怎麼做?還是維護換根的過程 當兩個點顏色相同的時候 答案顯然一樣,當不同的時候 可以分析得出 要查自己子樹內沒有自己父親顏色的祖先的節點個數。還要查 自己子樹之外沒有自己的顏色所庇護的節點個數。
第乙個很好查 預處理一下祖先庇護了哪寫節點 經過祖先的話就下方這些節點 通過線段樹維護dfs序很容易區間求和。
考慮第二個由於在不斷換根的過程中 有很多節點可以庇護自己子樹之外的節點 這個是存在輪換關係的 但是考慮和上一步的下方關係並不容易合併 或者說合併非常的困難所以這個做法是不成立的。
考試的時候我只是關心了 一下換根第乙個步應該怎麼做 卻沒有長遠的眼光看到換到若干步之後思路的錯誤。
果然 換根主要解決的問題 是自己父親那邊的處理問題 這點尤其重要。
只能換個思路了 。事實上對於樹上路徑資訊統計問題 或者說對於第一步暴力的優化 有乙個非常有效的做法 點分治。
我們可以嘗試利用點分治來維護剛才的暴力的過程 從而求解答案。
具體過程:考慮顏色數較少的情況 對於每一種顏色單獨點分治一次。
可以發現對於非當前分治重心的點來說 對於當前顏色 dfs統計一下其到分治重心的路徑上出現這種顏色了沒有 如果出現了 顯然這種顏色的貢獻為分治大小-這個點在當前分治重心下的子樹大小 考慮沒有出現 顯然是其他子樹內點到到分治重心出現這種顏色的點的個數-自己子樹中的這樣的點的個數。
考慮分治重心 顯然是所有子樹內到分治重心出現這種顏色的點的個數。
可以發現這個做法 可以拓展到多種顏色上 在點分治的時候預處理一下第二種貢獻再進行計算即可。
換根的**(雖然是錯誤的 但是只是換根的時候父親往上的那部分點沒有辦法在o(logn)的時間內處理罷了。
const int maxn=300010;
int n,len,cnt,top,id;ll ans1[maxn],ans;
int a[maxn],root[maxn],dfn[maxn],sz[maxn],c[maxn];
int lin[maxn],ver[maxn<<1],nex[maxn<<1];
struct wyt[maxn*30];
vectorg[maxn];
inline void add(int x,int y)
inline void dfs(int x,int fa)
c[a[x]]=ww;if(!ww)--ans;
}inline void change(int &p,int l,int r,int x,int w)
int mid=(l+r)>>1;
if(x<=mid)change(l(p),l,mid,x,w);
else change(r(p),mid+1,r,x,w);
sum(p)=sum(l(p))+sum(r(p));
}inline int ask(int p,int l,int r,int l,int r)
inline void dp(int x,int fa)
inline void get_root(int x,int fa)
son[x]=max(son[x],maxx-sz[x]);
if(son[x]其實核心就是分兩步討論。
4 3 省選模擬賽 石子遊戲 樹上博弈
注意觀察題目 每個點都只能將石子給自己的兩個兒子 且石子個數 1.顯然 這是乙個階梯nim.只有和最後一層的奇偶性相同的層才會有貢獻 證明也很顯然。那麼這其實就是近乎nim遊戲了 勝負自然取決於所有有貢獻的石子堆的異或和。但是 上午我傻了的一點 沒有分清sg函式和nim遊戲的聯絡。在nim遊戲中sg...
省選模擬賽 project
最小割問題。建如下邊 s,i,ai 代表選用a語言編寫第i個專案 i,t,bi 代表選用a語言編寫第i個專案 其後注意要反向連邊 i,j,d 代表選用b語言編寫第i個專案,選用a語言編寫第j個專案 j,i,c 代表選用a語言編寫第i個專案,選用b語言編寫第j個專案 litc學長出的題,引文最小割題目...
mirror 省選模擬賽
標籤 狀壓dp 結論 當最優情況下,每行每列鏡子的個數都為偶數 題目可以轉化為擺放鏡子,使得格仔中產生的光環最長 所以不需要考慮鏡子到底放什麼方向 於是我們直接狀壓一列鏡子當前的奇偶性進行轉移 時間複雜度o 4n n m2 o 4 n n m2 include include include inc...