【BZOJ3083】遥远的国度,树链剖分练习
2016-03-22 14:46
381 查看
传送门
写在前面:链剖裸题里的战斗机
思路:Drusher向我推荐了这道污题,据说他请Claris调了一周才A,于是我怀着忐忑的心情开始看题,其他操作都好,一个换根把我搞懵逼了,“套splay吗?”显然编程复杂度和时间复杂度都是极大的,每次换根又要重新剖分。后来看到了Lcomyn学长的讲解才大体明白,这里大家可以直接点开链接去看一下,但是我在调试第三种情况时出了一些问题,因为我用的是dfs序RMQ求lca,所以倍增求点时会出现一些奇怪的错误,20组数据WA了4组,无法只能借鉴zyf的暴力枚举法,通过记录下的搜索顺序判断x的儿子是否为root的祖先,若是则一定是我们要求的v
注意:小心数组越界,还有就是尽量不要用RMQ算法……
写在前面:链剖裸题里的战斗机
思路:Drusher向我推荐了这道污题,据说他请Claris调了一周才A,于是我怀着忐忑的心情开始看题,其他操作都好,一个换根把我搞懵逼了,“套splay吗?”显然编程复杂度和时间复杂度都是极大的,每次换根又要重新剖分。后来看到了Lcomyn学长的讲解才大体明白,这里大家可以直接点开链接去看一下,但是我在调试第三种情况时出了一些问题,因为我用的是dfs序RMQ求lca,所以倍增求点时会出现一些奇怪的错误,20组数据WA了4组,无法只能借鉴zyf的暴力枚举法,通过记录下的搜索顺序判断x的儿子是否为root的祖先,若是则一定是我们要求的v
注意:小心数组越界,还有就是尽量不要用RMQ算法……
#include<bits/stdc++.h> #define Inf 0x7fffffff using namespace std; int n,m,opt,cnt,tot,root,x,y,z; int pos[100010],num[400010],pre[100010],top[100010],fa[100010],son[100010],L[100010],R[100010],dep[100010],siz[100010],def[100010],first[100010]; int f[400010][20]; struct os { int u,v,next; }e[200010]; struct node { int minn,lazy; }tree[400010]; void add(int x,int y) { e[++tot].u=x; e[tot].v=y; e[tot].next=first[x]; first[x]=tot; } void pushdown(int now) { if (!tree[now].lazy) return; tree[now<<1].lazy=tree[now<<1].minn=tree[now].lazy; tree[now<<1|1].lazy=tree[now<<1|1].minn=tree[now].lazy; tree[now].lazy=0; } void dfs1(int now) { num[++num[0]]=now; pos[now]=num[0]; siz[now]=1; for (int i=first[now];i;i=e[i].next) if (e[i].v!=fa[now]) { dep[e[i].v]=dep[now]+1; fa[e[i].v]=now; dfs1(e[i].v); num[++num[0]]=now; if (siz[e[i].v]>siz[son[now]]) son[now]=e[i].v; siz[now]+=siz[e[i].v]; } } void dfs2(int now,int tp) { top[now]=tp; L[now]=++cnt; pre[cnt]=now; if (son[now]) dfs2(son[now],tp); for (int i=first[now];i;i=e[i].next) if (e[i].v!=son[now]&&e[i].v!=fa[now]) dfs2(e[i].v,e[i].v); R[now]=cnt; } void init()//RMQ预处理 { int x,y; for (int i=1;i<=num[0];i++) f[i][0]=num[i]; for (int i=1;i<=log2(num[0]);i++) for (int j=1;j<=num[0]-(1<<i);j++) { x=f[j][i-1];y=f[j+(1<<(i-1))][i-1]; if (dep[x]>dep[y]) f[j][i]=y; else f[j][i]=x; } } void build(int now,int begin,int end) { if (begin==end){tree[now].minn=def[pre[end]];return;} int mid=(begin+end)>>1; build(now<<1,begin,mid); build(now<<1|1,mid+1,end); tree[now].minn=min(tree[now<<1].minn,tree[now<<1|1].minn); } void update(int now,int begin,int end,int l,int r) { if (l<=begin&&end<=r) {tree[now].minn=tree[now].lazy=z;return;} pushdown(now); int mid=(begin+end)>>1; if (mid>=l) update(now<<1,begin,mid,l,r); if (mid<r) update(now<<1|1,mid+1,end,l,r); tree[now].minn=min(tree[now<<1].minn,tree[now<<1|1].minn); } int get(int now,int begin,int end,int l,int r) { if (l<=begin&&end<=r) return tree[now].minn; pushdown(now); int mid=(begin+end)>>1,ans=Inf; if (mid>=l) ans=min(ans,get(now<<1,begin,mid,l,r)); if (mid<r) ans=min(ans,get(now<<1|1,mid+1,end,l,r)); tree[now].minn=min(tree[now<<1].minn,tree[now<<1|1].minn); return ans; } int lca(int x,int y) { int pos1=pos[x],pos2=pos[y]; if (pos1>pos2) swap(pos1,pos2); int mid=log2(pos2-pos1+1); x=f[pos1][mid];y=f[pos2-(1<<mid)+1][mid]; if (dep[y]>dep[x]) return x; else return y; } void solve(int l,int r) { int f1=top[l],f2=top[r]; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(l,r),swap(f1,f2); update(1,1,cnt,L[f1],L[l]); l=fa[f1];f1=top[l]; } if (dep[l]>dep[r]) swap(l,r); update(1,1,cnt,L[l],L[r]); } main() { scanf("%d%d",&n,&m); for (int i=1;i<n;i++) scanf("%d%d",&x,&y), add(x,y),add(y,x); for (int i=1;i<=n;i++) scanf("%d",&def[i]); scanf("%d",&root); dfs1(1); dfs2(1,1); init(); build(1,1,cnt); while (m--) { scanf("%d",&opt); if (opt==1) scanf("%d",&root); else if (opt==2) scanf("%d%d%d",&x,&y,&z),solve(x,y); else { scanf("%d",&x); if (x==root) printf("%d\n",tree[1].minn); else if (lca(x,root)!=x) printf("%d\n",get(1,1,cnt,L[x],R[x])); else { int ans=Inf; for (int i=first[x];i;i=e[i].next) if(L[e[i].v]<=L[root]&&R[e[i].v]>=R[root]) { z=e[i].v; break; } if (L[z]>1) ans=min(ans,get(1,1,cnt,1,L[z]-1)); if (R[z]<n) ans=min(ans,get(1,1,cnt,R[z]+1,n)); printf("%d\n",ans); } } } }
相关文章推荐
- 类MVP实践报告
- 音频数字化原理
- 4款.Net报表控件优势对比分析
- 转一篇shared_ptr的小文 http://www.cnblogs.com/welkinwalker/archive/2011/10/20/2218804.html
- CSRF Token介绍与应对策略
- iOS app 多语言本地化,主流大国语言对照表
- 正则表达式基础
- 常用正则整理
- Vue 技巧
- php 正则表达式 将形如 "天," ,"安", "门" 转化为"天、安、门", (仅匹配汉字)
- 那些OVER的封装
- 动态定价
- Git 查看某个版本修改了哪些文件
- git分享(一)git clone
- hdu5025
- Android中java调用C的实现jniNDK
- UVa 327 - Evaluating Simple C Expressions
- unity限制目标物旋转角度
- 虚拟化网络之OpenvSwitch(二)
- makefile中的notdir,wildcard和patsubst