1. 程式人生 > 實用技巧 >vue對錶單、表格的應用

vue對錶單、表格的應用

CF1017G The Tree

給定一棵樹,三種操作:

  1. \(x\) 染黑,如果其為黑色,那麼對子樹遞迴。
  2. \(x\) 的子樹染白。
  3. 查詢 \(x\) 的顏色。

\(n,m\le 10^5\)

Solution

考慮鏈的情況怎麼做。

不考慮操作 \(2\),假設已知我們進行了若干次操作 \(1\),如何判定點 \(x\) 的顏色。

假設某個點執行了操作 \(2\) 那麼給其權值 \(+1\),那麼考慮從某個 \(u<x\) 處起,如果直到 \(x\) 這一段區間的點權和大於 \(u\to x\) 的距離那麼顯然就是可以的。

於是條件等價於 \(\exist ~u<x,dis_x-dis_u\le w_x-w_u\)

\(\min(w_u-dis_u)\le w_x-dis_x\)

這個做法是可以拓展到樹上的。

接下來考慮操作 \(2\),我們發現我們不好刪除之前的操作 \(1\) 的影響。

那麼不妨認為操作 \(2\) 帶來了獨立的影響!我們先清空子樹內的增加權值,再給 \(x\) 處增加一個負點權,使得 \(x\) 處的答案剛好被消去即可。設增加的權值為 \(c\),那麼我們希望的是不存在 \(u\) 滿足 \(dis_x-dis_u\le w_x-w_u\)

\(dis_x-dis_u> w_x-w_u+c,w_u-dis_u>w_x-dis_x+c\),故 \(c\) 即兩者差減 \(1\)

\(0\)\(\max\)

不難發現其正確性,這個演算法可以剛好使得 \(2\) 的影響為消去子樹貢獻。

於是我們只需要支援:查詢鏈上最大值,和子樹修改,單點修改,單點查詢等操作。

可以通過樹鏈剖分來解決這個問題,複雜度為 \(\mathcal O(m\log^2 n)\)


還有一個非常仙的做法:

考慮對查詢進行分塊,設塊的大小為 \(cnt\),現在將一個塊內的所有查詢涉及到的點拿出來建虛樹。

這樣我們得到了一個大小為 \(cnt\) 的樹。

對於每條邊,維護邊上的點數,和邊上白色點的數量。

考慮修改,對於操作 \(1\) 暴力修改即可,注意維護邊上的資訊。

對於操作 \(2\)

,暴力清空子樹邊上的白色點數量為原點數。

對於查詢,直接輸出即可。

每處理完一個塊之後,我們通過 Dfs 暴力重構這棵樹即可。

複雜度為 \(\mathcal O(n\cdot cnt+\frac{n^2}{cnt})\),平衡可以做到 \(\mathcal O(n\sqrt{n})\)(這裡認為 \(n,q\) 同級別)

這裡的建虛樹是通過 Dfs 建的。

\(Code:\)

#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
int gi() {
	char cc = getchar() ; int cn = 0, flus = 1 ;
	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
	return cn * flus ;
}
const int inf = 1e9 + 5 ; 
const int N = 2e5 + 5 ;
int n, q, idnex, L[N], R[N], Id[N] ;
int top[N], f[N], dep[N], sz[N], son[N] ;
vector<int> G[N] ; 
struct Tr { int w, c, tag, mark ; } tr[N << 2] ;
void dfs1(int x, int fa) {
	f[x] = fa, dep[x] = dep[fa] + 1, sz[x] = 1 ;
	for(int v : G[x]) {
		dfs1(v, x), sz[x] += sz[v] ;
		if( sz[v] > sz[son[x]] ) son[x] = v ; 
	} 
}
void dfs2(int x, int high) {
	top[x] = high, L[x] = ++ idnex, Id[idnex] = x ; 
	if(son[x]) dfs2(son[x], high) ;
	for(int v : G[x]) if( v ^ son[x] ) dfs2(v, v) ;
	R[x] = idnex ; 
}
void pushup(int x) { tr[x].w = min(tr[ls(x)].w, tr[rs(x)].w ) ; }
void Col(int x) {
	tr[x].mark = 1, tr[x].w = tr[x].c, tr[x].tag = 0 ; 
}
void pushmark(int x) {
	if( tr[x].mark ) Col(ls(x)), Col(rs(x)), tr[x].mark = 0 ; 
	int s = tr[x].tag ; tr[x].tag = 0 ;
	tr[ls(x)].tag += s, tr[rs(x)].tag += s,
	tr[ls(x)].w += s, tr[rs(x)].w += s ;  
}
void build(int x, int l, int r) {
	if( l == r ) return tr[x].w = tr[x].c = -dep[Id[l]], void() ;
	int mid = (l + r) >> 1 ; 
	build(ls(x), l, mid), build(rs(x), mid + 1, r), pushup(x), tr[x].c = tr[x].w ; 
}
void Cover(int x, int l, int r, int ql, int qr) {
	if( ql <= l && r <= qr ) return Col(x), void() ; 
	if( qr < l || r < ql ) return ; 
	int mid = (l + r) >> 1 ; pushmark(x) ; 
	Cover(ls(x), l, mid, ql, qr), Cover(rs(x), mid + 1, r, ql, qr), pushup(x) ; 
}
void update(int x, int l, int r, int ql, int qr, int k) {
	if( ql <= l && r <= qr ) return tr[x].w += k, tr[x].tag += k, void() ; 
	if( qr < l || r < ql ) return ; 
	int mid = (l + r) >> 1 ; pushmark(x) ; 
	update(ls(x), l, mid, ql, qr, k), 
	update(rs(x), mid + 1, r, ql, qr, k), pushup(x) ; 
}
int query(int x, int l, int r, int ql, int qr) {
	if( ql <= l && r <= qr ) return tr[x].w ; 
	if( qr < l || r < ql ) return 0 ;
	int mid = (l + r) >> 1 ; pushmark(x) ;
	return min(query(ls(x), l, mid, ql, qr), query(rs(x), mid + 1, r, ql, qr)) ; 
}
int Q(int x) { 
	int ans = inf ; 
	while( x != 1 ) ans = min( ans, query( 1, 1, n, L[top[x]], L[x]) ), x = f[top[x]] ; 
	ans = min( ans, query(1, 1, n, L[top[x]], L[x]) ) ;
	return ans ; 
}
void White(int x) {
	Cover(1, 1, n, L[x], R[x]) ; 
	int c = Q(f[x]), w = query(1, 1, n, L[x], L[x]) ; 
	c = max( 0, c - w - 1 ), update(1, 1, n, L[x], R[x], c) ; 
}
void Query(int x) {
	int c = Q(f[x]), w = query(1, 1, n, L[x], L[x]) ; 
	if( c <= w ) puts("black") ;
	else puts("white") ; 
} 
signed main()
{
	n = gi() + 1, q = gi() ; int opt, x ; 
	rep( i, 3, n ) x = gi() + 1, G[x].push_back(i) ; 
	G[1].push_back(2) ; 
	dfs1(1, 1), dfs2(1, 1), build(1, 1, n) ;
	rep( i, 1, q ) {
		opt = gi(), x = gi() + 1 ; 
		if( opt == 1 ) update(1, 1, n, L[x], R[x], 1) ;
		if( opt == 2 ) White(x) ; 
		if( opt == 3 ) Query(x) ;  
	}
	return 0 ;
}