發現和sdoi2017樹點塗色差不多 但是當時這道題模擬賽的時候不會寫 賽後也沒及時訂正 所以這場模擬賽的這道題雖然秒想到了lct和線段樹但是最終還是只是打了暴力。
痛定思痛 還是要把這道題給補了。
但是對於這道題來說 暴力還是有價值的。
考慮20分 每次暴力dfs.
考慮對於樹是隨機生成的 那麼期望高度為logn 我們發現每次修改只用修改到1 也就是說每次暴力修改顏色的話只需要logn的時間複雜度.
考慮如何動態維護子樹內的值 考慮修改乙個點的顏色 子樹內之前和它顏色一樣的點 顯然子樹內部整體答案+1 如果不一樣那麼沒有影響 和當前一樣也沒有影響。
考慮這個點和它的父親此時答案是一樣的如果原來答案也是一樣的 那麼沒有任何的修改 如果不一樣 那麼子樹內部整體-1.
依靠這個思路我們可以 維護一棵線段樹 logn的時間內進行區間修改 區間查詢。
考慮100分的做法 發現我們暴力慢的地方在於每次都要向上跳。
有優化的地方是 如果當前點可能樹上的一段區間顏色是一樣的 我們只需要在 當前修改節點x和那段顏色一樣的點y的lca處修改 剩下的直接向上跳即可。
換個角度 其實這個染顏色其實像是lct 的access操作 這樣我們就可以很方便的維護上述的操作。
考慮這樣做的向上跳的複雜度 可以發現利用lct的性質 均攤logn.
所以每次在access的時候 完成子樹內部的修改即可。維護dfs序線段樹 複雜度nlog^2.
const int maxn=150010;
int n,q,len,cnt;
int lin[maxn],c[maxn][2],f[maxn],ver[maxn<<1],nex[maxn<<1],dfn[maxn],out[maxn];
int fa[maxn],d[maxn],sz[maxn],son[maxn],top[maxn],v[maxn];
inline void add(int x,int y)
inline void dfs(int x)
}inline void dfs(int x,int father)
inline int lca(int x,int y)
inline void change(int p,int l,int r,int x)
int mid=(l(p)+r(p))>>1;
if(tag(p))pushdown(p);
if(l<=mid)change(zz,l,r,x);
if(r>mid)change(yy,l,r,x);
pushup(p);
}inline int ask(int p,int x)
inline int ask(int p,int l,int r)
inline ll asksum(int p,int l,int r)
inline void asksum(int x)
inline int pd(int x)//判斷x是否為根.
inline void rotate(int x)
inline void splay(int x)
}inline int findroot(int x)
inline void access(int x)
if(y)
c[x][1]=y;
y=x;x=f[x]; }}
int main()
get(q);dfs(1);dfs(1,1);
build(1,1,n);
rep(1,n,i)f[i]=fa[i];
rep(1,q,i)
return 0;
}
省選模擬賽 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...
Sequence 省選模擬賽
標籤 貪心 給定乙個整數數列 a,定義f a max1 inaj aif a max1 i naj ai 保證 f a 0。你需要求出至少需要修改 a 的多少個位置才能使 f a 變小。注意,你修改之後的數也必須是整數。2 n 106 ai 109 2 n 106 ai 109 簽到題gg,自己真的...