codeforce 342E 树链剖分 || 分块

题目链接:http://codeforces.com/problemset/problem/342/E

树链剖分代码:

#include
#include
#include
#include
using namespace std;
#define yt eg[i].to
#define lson l,m,a[rt].ls
#define rson m+1,r,a[rt].rs
#define pb push_back
const int N=100005,inf=1000001;
int cnt,v[N],fa[N],top[N],w[N],dep[N],size[N],son[N];
//size[i]以i为根的子树节点数
//son[i] i的子树中,节点数最多的儿子节点
int dis[N],root[N],id,sz;
vector lk[N];

inline int min(int a,int b){return a size[son[x]]) son[x] = yt;
	}
}
int dfs2(int x,int tp){//转成1为根的有根树 对于多个子节点先走重链 再走轻边,这样可以使重链在线段树中连续分布
	top[x] = tp;//x的所在重链的顶端节点
	int sz = lk[tp].size();
	w[x] = sz, lk[tp].pb(x);//w[i] 表示lk数组中所在的位置 lk[ top[i] ][w[i]] = i(线段树中的位置)
	if(son[x]) 
		dfs2(son[x], tp);
	for(int i = v[x]; ~i ; i = eg[i].next)
		if(yt != son[x] && yt != fa[x]) 
			dfs2(yt, yt);
}
void build(int tp,int l,int r,int rt){
	a[rt].ml = a[rt].mr = inf;
	if(l == r) return;
	int m = (l + r)>>1;
	a[rt].ls = id++, a[rt].rs = id++;
	build(tp,lson),build(tp,rson);
}
void update(int p, int c, int l, int r, int rt){
	if(l == r)
	{
		a[rt].ml = l+c;
		a[rt].mr = sz-1-l+c;
		return;
	}
	int m = (l+r)>>1;
	if(p <= m) update(p, c, lson);
	else update(p, c, rson);
	pushup(rt);
}
int query(int L, int R, int k, int l, int r, int rt){
	if(L <= l && r<= R){
		if(!k) return a[rt].ml;
		else return a[rt].mr;
	}
	int m = (l + r)>>1, ret = inf;
	if(L<=m) ret = min(ret, query(L, R, k, lson));
	if(R >m) ret = min(ret, query(L, R, k, rson));
	return ret;
}
int main(){
	int T, op, n, m, i, j, k, x, y, c, f1, f2, t, d, tp, res;
	while(~scanf("%d %d", &n, &m))
	{
		for(i = 1;i <= n; i++) dis[i] = inf,lk[i].clear();
		memset(v, -1, sizeof(v));
		memset(fa, 0, sizeof(fa));
		for(i = cnt = 0;i < n-1; i++)
		{
			scanf("%d %d", &x, &y);
			add(x, y), add(y, x);
		}
		dep[1] = dis[1] = 0, dfs1(1);
		id = cnt = 0, dfs2(1, 1);
		for(i = 1;i <= n; i++)
		{
			sz = lk[i].size();
			if(top[i] == i && sz != 1)//若i是重链起点 且i不是叶子节点 也就是有重链时
			{
				root[i] = id ++;
				build(i, 0, sz-1, root[i]);
			}
		}
		sz = lk[1].size();
		update(0, 0, 0, sz-1, root[1]);
		while(m--)
		{
			scanf("%d%d", &op, &x);
			if(op==1)
			{
				for(y = x; y ;y = fa[tp])
				{
					tp = top[y];
					sz = lk[tp].size();
					if(dis[y] > dep[x] - dep[y])
					{
						dis[y] = dep[x] - dep[y];
						if(sz > 1) update(w[y], dis[y], 0, sz-1, root[tp]);
					}
					else break;
				}
			}
			else{
				for(res = inf, y = x; y ; y = fa[tp]){
					tp = top[y];
					sz = lk[tp].size();
					if(sz == 1) res = min(res, dis[y] + dep[x] - dep[y]);
					else{
						res=min(res,query(0,w[y],1,0,sz-1,root[tp])+w[y]-(sz-1)+dep[x]-dep[y]);
						res=min(res,query(w[y],sz-1,0,0,sz-1,root[tp])-w[y]+dep[x]-dep[y]);
					}
				}
				printf("%d\n",res);
			}
		}
	}
	return 0;
}


 

 分块代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
typedef pair pii;
const int N=(int)1e5+10;
vectorG[N],black,white;
int dep[N],dp[N];
const int Pow = 18;
int par[N][Pow];
void dfs(int u,int pre){
	dep[u] = dep[pre] + 1;
	par[u][0] = pre;
	for(int i=1;i dep[b])swap(a,b);
	if(dep[a] < dep[b]){
		int del = dep[b] - dep[a];
		for(int i=0;i=0;i--)
			if(par[a][i] != par[b][i])
				a = par[a][i],b = par[b][i];
		a = par[a][0],b = par[b][0];
	}
	return a;
}
void bfs(){
	queueQ;
	for(int i=0;i dp[u] + 1){
				dp[v] = dp[u] + 1;
				Q.push(v);
			}
		}
	}
	black.clear();
}
int main(){
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;i++)G[i].clear();
		for(int i=1;i<=n;i++)dp[i] = ~0u>>2;
		black.clear();black.push_back(1);
		for(int i=1;i


 

你可能感兴趣的:(树链剖分,codeforce)