codeforce 342E 树链剖分 || 分块

来源:互联网 发布:客管家软件评价 编辑:程序博客网 时间:2024/04/29 18:00

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

树链剖分代码:

#include<stdio.h>#include<memory.h>#include<algorithm>#include<vector>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_backconst 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<int> lk[N];inline int min(int a,int b){return a<b?a:b;}struct node{int opt,ml,mr,ls,rs;}a[N<<2];struct edge{int to,next;}eg[N<<1];void add(int x,int y){eg[cnt].to=y;eg[cnt].next=v[x];v[x]=cnt++;}int pushup(int rt){int ls=a[rt].ls,rs=a[rt].rs;a[rt].ml=min(a[ls].ml,a[rs].ml);a[rt].mr=min(a[ls].mr,a[rs].mr);}int dfs1(int x){//得到重链son[x]=0, size[x]=1;for(int i=v[x];i!=-1;i=eg[i].next){if(yt==fa[x]) continue;fa[yt] = x;dep[yt] = dep[x]+1;dfs1(yt);size[x] += size[yt];if(size[yt] > 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<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cstdlib>#include<cassert>#include<algorithm>#include<iostream>#include<string>#include<deque>#include<vector>#include<queue>#include<list>#include<stack>#include<set>#include<map>#include<bitset>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;typedef long long ll;typedef pair<int,int> pii;const int N=(int)1e5+10;vector<int>G[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<Pow;i++)par[u][i] = par[par[u][i-1]][i-1];for(int i=0;i<G[u].size();i++){int v = G[u][i];if(v == pre)continue;dfs(v,u);}}int LCA(int a,int b){if(dep[a] > dep[b])swap(a,b);if(dep[a] < dep[b]){int del = dep[b] - dep[a];for(int i=0;i<Pow;i++)if(del&(1<<i))b = par[b][i];}if(a!=b){for(int i=Pow-1;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(){queue<int>Q;for(int i=0;i<black.size();i++){Q.push(black[i]);dp[black[i]] = 0;}while(!Q.empty()){int u = Q.front();Q.pop();for(int i=0;i<G[u].size();i++){int v =G[u][i];if(dp[v] > 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<n;i++){int u,v;scanf("%d%d",&u,&v);G[u].push_back(v);G[v].push_back(u);}dfs(1,0);bfs();int maxn = sqrt(m*1.0) + 1;for(int i=0;i<m;i++){int op,u;scanf("%d%d",&op,&u);if(op==1){black.push_back(u);if(black.size() == maxn){bfs();}}else{int sz = black.size();int ans = dp[u];for(int i=0;i<sz;i++){int v = black[i];ans = min(ans,dep[u] + dep[v] - 2*dep[LCA(u,v)]);}printf("%d\n",ans);}}}return 0;}


 

0 0
原创粉丝点击