Codeforeces 342E 对操作分块

1. 在此之前我掌握的分块算法仅指 用 Sqrt(n)的时间回答一次询问

2. 这道题和之前做过的一道AC-machine的题目非常像,也是分块做法。一批一批的处理动态更新,询问的结果一般由两部分共同组成。

3. 另外这道题更新的时候显然bfs比dfs更优秀


#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cmath>
#include <vector>
#include <sstream>
#include <bitset>
#include <deque>
#include <iomanip>
using namespace std;
#define pr(x) cout << #x << " = " << x << endl;
#define bug cout << "bugbug" << endl;
#define ppr(x, y) printf("(%d, %d)\n", x, y);
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n---------------")

typedef long long ll;
typedef double DBL;
typedef pair<int, int> P;
typedef unsigned int uint;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1e5 + 4;
const int maxm = 1e4 + 4;
const double pi = acos(-1.0);
int u, v, cmd, n, q, st[maxn][20], dp[maxn], depth[maxn];
bool red[maxn];
vector<int> G[maxn];
void init(){
	for (int i = 1; i < 20; ++i)
		for (int j = 1; j <= n; ++j)
			st[j][i] = st[st[j][i-1]][i-1];
}
int LCA(int u, int v){
	if (depth[u] > depth[v]) swap(u, v);
	int Sub = depth[v] - depth[u];
 	for (int i = 0; i < 20; ++i)
 		if (Sub >> i & 1) v = st[v][i];
 	if (u == v) return Sub;
 	int up = 0;
	for (int i = 19; i > -1; --i)
 		if (st[u][i] != st[v][i]){
 			up += 1 << i;
 			u = st[u][i];
 			v = st[v][i];
		}
	return Sub + up * 2 + 2;
}
void DFS(int u, int f, int deep){
	st[u][0] = f;
	depth[u] = deep;
	for (int i = 0; i < G[u].size(); ++i){
		int to = G[u][i];
		if (to == f) continue; 
		DFS(to, u, deep+1);
	}
	return;
} 
void dfs1(int u){
	if (red[u]) dp[u] = 0;
	for (int i = 0; i < G[u].size(); ++i){
		int to = G[u][i];
		if (to == st[u][0]) continue;
		dfs1(to);
		dp[u] = min(dp[u], dp[to] + 1);
	}
	return;
}
void dfs2(int u){
	if (u != 1) dp[u] = min(dp[u], dp[st[u][0]] + 1);
	for (int i = 0; i < G[u].size(); ++i){
		int to = G[u][i];
		if (to == st[u][0]) continue;
		dfs2(to);
	} 
	return;
}
vector<int> change;
queue<P> Q;
void bfs(){
	for (int i = 0; i < change.size(); ++i){
		Q.push(P(change[i], 0));
		dp[change[i]] = 0;
	}
	while(Q.size()){
		P top = Q.front(); Q.pop();
		u = top.first, v = top.second;
		for (int i = 0; i < G[u].size(); ++i){
			int to = G[u][i];
			if (dp[to] > v + 1){
				dp[to] = v + 1;
				Q.push(P(to, v+1));
			}
		}
	}
	return;
}
int main(){
//必须编译过才能交
//	ios::sync_with_stdio(false);
	int ik, i, j, k, kase;
	scanf("%d%d", &n, &q);
	memset(dp, 0x3f, sizeof dp);
	for (i = 1; i < n; ++i){
		scanf("%d%d", &u, &v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	
	DFS(1, 1, 1);
	init();
	memset(red, 0, sizeof red);
	red[1] = true;
	dfs1(1);
	dfs2(1);
	int bk = sqrt(n);
	while(q--){
		scanf("%d%d", &cmd, &u);
		if (cmd == 1){
			change.push_back(u);
			red[u] = true;
			if (change.size() == bk){
				bfs();
				change.clear();
			}
		}else{
			int ans = dp[u];
			for (i = 0; i < change.size(); ++i)
				ans = min(ans, LCA(u, change[i]));
//			pr(ans);
			printf("%d\n", ans);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值