[BZOJ3083]遥远的国度(链剖+dfs序)
2016-03-21 13:58
344 查看
题目描述
传送门题解
讲解转自lcomyn学长的博客:http://blog.csdn.net/lcomyn/article/details/45718295非常详细一直不停地RE,是查询的时候出问题了。注意以后枚举儿子的时候注意一定不是它的父亲(双向存边)。
代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=200100; const int max_sum=max_n*5; const int max_e=max_n*2; const int INF=2147483647; int n,m,x,y,opt,id,p1,p2,val; int w[max_n]; int N,root,ans; int tot,point[max_n],next[max_e],v[max_e]; int sum[max_sum],delta[max_sum]; int father[max_n],son[max_n],h[max_n],size[max_n]; int top[max_n],in[max_n],out[max_n],num[max_n]; inline void addedge(int x,int y){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; } inline void dfs_1(int x,int fa,int dep){ size[x]=1; h[x]=dep; father[x]=fa; int maxson=0; for (int i=point[x];i;i=next[i]) if (v[i]!=fa){ dfs_1(v[i],x,dep+1); size[x]+=size[v[i]]; if (size[v[i]]>maxson){ maxson=size[v[i]]; son[x]=v[i]; } } } inline void dfs_2(int x,int fa){ if (son[fa]!=x) top[x]=x; else top[x]=top[fa]; in[x]=++N; if (son[x]) dfs_2(son[x],x); for (int i=point[x];i;i=next[i]) if (v[i]!=fa&&v[i]!=son[x]) dfs_2(v[i],x); out[x]=N; } inline void update(int now){ sum[now]=min(sum[now<<1],sum[now<<1|1]); } inline void pushdown(int now,int l,int r,int mid){ if (delta[now]){ sum[now<<1]=delta[now]; delta[now<<1]=delta[now]; sum[now<<1|1]=delta[now]; delta[now<<1|1]=delta[now]; delta[now]=0; } } inline void build(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ sum[now]=w[num[l]]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now); } inline void interval_change(int now,int l,int r,int lrange,int rrange,int v){ int mid=(l+r)>>1; if (lrange<=l&&r<=rrange){ sum[now]=v; delta[now]=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) interval_change(now<<1,l,mid,lrange,rrange,v); if (mid+1<=rrange) interval_change(now<<1|1,mid+1,r,lrange,rrange,v); update(now); } inline int query(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=INF; if (lrange<=l&&r<=rrange) return sum[now]; pushdown(now,l,r,mid); if (lrange<=mid) ans=min(ans,query(now<<1,l,mid,lrange,rrange)); if (mid+1<=rrange) ans=min(ans,query(now<<1|1,mid+1,r,lrange,rrange)); return ans; } inline void CHANGE(){ int f1=top[p1],f2=top[p2]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(f1,f2); swap(p1,p2); } interval_change(1,1,N,in[f1],in[p1],val); p1=father[f1]; f1=top[p1]; } if (in[p1]>in[p2]) swap(p1,p2); interval_change(1,1,N,in[p1],in[p2],val); } inline void QUERY(){ if (id==root){ ans=query(1,1,N,1,N); printf("%d\n",ans); return; } if (in[root]<in[id]||in[root]>out[id]){ ans=query(1,1,N,in[id],out[id]); printf("%d\n",ans); return; } for (int i=point[id];i;i=next[i]) if (v[i]!=father[id]&&in[root]>=in[v[i]]&&in[root]<=out[v[i]]){ ans=query(1,1,N,1,in[v[i]]-1); if (out[v[i]]!=N) ans=min(ans,query(1,1,N,out[v[i]]+1,N)); printf("%d\n",ans); return; } } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<n;++i){ scanf("%d%d",&x,&y); addedge(x,y); } for (int i=1;i<=n;++i) scanf("%d",&w[i]); scanf("%d",&id); root=id; dfs_1(id,0,1); dfs_2(id,0); for (int i=1;i<=n;++i) num[in[i]]=i; build(1,1,N); for (int i=1;i<=m;++i){ scanf("%d",&opt); switch(opt){ case 1:{ scanf("%d",&id); root=id; break; } case 2:{ scanf("%d%d%d",&p1,&p2,&val); CHANGE(); break; } case 3:{ scanf("%d",&id); QUERY(); break; } } } return 0; }
总结
枚举儿子的时候注意一定不是它的父亲(双向存边)。相关文章推荐
- Java开发工具中Compile、Make和Build的区别
- MySQL中的共享锁与排他锁
- 串口控制小夜灯
- LVS之VS/DR搭建web集群实战!!!
- /sys/block/xxx/queue/中的max_hw_sectors_kb 和 max_sectors_kb
- Device Tree(三):代码分析
- iOS中的滤镜
- 快速掌握Lua 5.3 —— 扩展你的程序 (2)
- 魔鬼牧师游戏--简单工厂的改进
- 自定义布局
- halcon小例:ORC识别
- 怎么实现EDIUS中添加的图片素材一样大
- MySQL中的行级锁,表级锁,页级锁
- wampserver3.0 图标为黄色解决
- 欢迎使用CSDN-markdown编辑器
- Java-网络编程
- mysql索引原理及慢查询优化
- SDK 组件 Qupaisdk 启动出错,错误消息为 [Qupaisdk], the android stack error message is Fail to start the plugin, which is caused by Failed resolution of: Lcom/duanqu/qupai/recorder/R$array;
- ShopNC中使用QQ互联遇到的坑
- Spark On YARN 环境搭建