BZOJ 3083 遥远的国度 树链剖分
来源:互联网 发布:rc补偿网络 编辑:程序博客网 时间:2024/05/22 02:01
题目大意:给定一棵有根树,每个点有一个权值,提供三种操作:
1.将x节点变为根节点
2.将x到y路径上的点的权值全部改为v
3.询问x的子树中点权的最小值
树链剖分没商量!不过由于是查询子树的最小权值,所以我们选择DFS序剖分,而不是先前的轻重链剖分
即每个节点第一个遍历到的儿子是亲儿子 重标号就是DFS序
↑请无视本沙茶的一本道……轻重链剖分本来就能修改子树,我一直以来写的都是沙茶版……特此更正,希望大家别被我这个沙茶误导了
然后就好办了 换根的话不用真的换 只需要记录当前的根节点 然后求解时分三种情况讨论
1.root在x的子树中但不为x 此时枚举x的子节点y 若root在y的子树中 则求子树y的补集
2.root=x x是根节点 x的子树就是整棵树 此时直接输出全集
3.root不在x的子树中 此时直接输出x的子树的最小权值即可
很好写的一道题,挂了一下午。。。。。RE了三遍,干掉三个BUG,然后发现原来是freopen没删。。。交上去还是WA,这时发现少讨论第二种情况。。
最后写完是4000-MS。。。 今天是肿了么怎么写的这么惨。。。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define ls tree[p].lson#define rs tree[p].rson#define M 100100using namespace std;struct Tree{ int num,mark; int lson,rson;}tree[M<<1];struct abcd{ int to,next;}table[M<<1];int head[M],tot;int n,m,root,treetot,f[M],fa[M],dpt[M],top[M],son[M],pos[M],last[M],posf[M],cnt;void add(int x,int y){ table[++tot].to=y; table[tot].next=head[x]; head[x]=tot;}void dfs(int x){ int i,lastson=0; dpt[x]=dpt[fa[x]]+1; pos[x]=++cnt; if(son[fa[x]]==x) top[x]=top[fa[x]]; else top[x]=x; for(i=head[x];i;i=table[i].next) { if(table[i].to==fa[x]) continue; fa[table[i].to]=x; if(!son[x]) son[x]=table[i].to; lastson=table[i].to; dfs(table[i].to); } if(lastson)last[x]=last[lastson]; else last[x]=pos[x];}void Build_Tree(int p,int x,int y){ int mid=x+y>>1; if(x==y) { tree[p].num=posf[mid]; return ; } ls=++treetot;rs=++treetot; Build_Tree(ls,x,mid); Build_Tree(rs,mid+1,y); tree[p].num=min(tree[ls].num,tree[rs].num);}void update(int p,int x,int y,int l,int r,int v){ int mid=x+y>>1; if(x==l&&y==r) { tree[p].num=tree[p].mark=v; return ; } if(tree[p].mark) { tree[ls].num=tree[ls].mark=tree[p].mark; tree[rs].num=tree[rs].mark=tree[p].mark; tree[p].mark=0; } if(r<=mid) update(ls,x,mid,l,r,v); else if(l>mid) update(rs,mid+1,y,l,r,v); else update(ls,x,mid,l,mid,v),update(rs,mid+1,y,mid+1,r,v); tree[p].num=min(tree[ls].num,tree[rs].num);}void change(int x,int y,int z){ int fx=top[x],fy=top[y]; while(fx!=fy) { if(dpt[fx]<dpt[fy]) swap(x,y),swap(fx,fy); update(0,1,n,pos[fx],pos[x],z); x=fa[fx];fx=top[x]; } if(dpt[x]<dpt[y]) swap(x,y); update(0,1,n,pos[y],pos[x],z);}int getans(int p,int x,int y,int l,int r){ int mid=x+y>>1; if(x==l&&y==r) return tree[p].num; if(tree[p].mark) { tree[ls].num=tree[ls].mark=tree[p].mark; tree[rs].num=tree[rs].mark=tree[p].mark; tree[p].mark=0; } if(r<=mid) return getans(ls,x,mid,l,r); else if(l>mid) return getans(rs,mid+1,y,l,r); else return min( getans(ls,x,mid,l,mid) , getans(rs,mid+1,y,mid+1,r) );}int query(int x){if(x==root) return getans(0,1,n,1,n); if(pos[root]<pos[x]||pos[root]>last[x]) return getans(0,1,n,pos[x],last[x]); int i,re=0x7fffffff; for(i=head[x];i;i=table[i].next) if(pos[root]>=pos[table[i].to]&&pos[root]<=last[table[i].to]&&table[i].to!=fa[x]) break; re=min(re,getans(0,1,n,1,pos[table[i].to]-1)); if(last[table[i].to]!=n) re=min(re,getans(0,1,n,last[table[i].to]+1,n)); return re;}int main(){ int i,x,y,z,p; cin>>n>>m; for(i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x); for(i=1;i<=n;i++) scanf("%d",&f[i]); cin>>root; dfs(root); for(i=1;i<=n;i++) posf[pos[i]]=f[i]; Build_Tree(0,1,n); for(i=1;i<=m;i++) { scanf("%d",&p); if(p==1) scanf("%d",&root); else if(p==2) scanf("%d%d%d",&x,&y,&z),change(x,y,z); else scanf("%d",&x),printf("%d\n",query(x)); }}
2 0
- BZOJ 3083 遥远的国度 树链剖分
- BZOJ 3083 遥远的国度 树链剖分
- BZOJ 3083 遥远的国度 树链剖分
- BZOJ 3083 遥远的国度 树链剖分
- 【BZOJ 3083】遥远的国度
- bzoj 3083 遥远的国度
- BZOJ 3083 遥远的国度
- bzoj 3083: 遥远的国度
- 【树链剖分+dfs序】【bzoj 3083】: 遥远的国度
- 【bzoj 3083】遥远的国度(树链剖分+线段树)
- BZOJ 3083 遥远的国度 树链剖分 线段树
- bzoj 3083: 遥远的国度 树链剖分+倍增lca
- 【BZOJ 3083】遥远的国度 树剖
- 3083: 遥远的国度|树链剖分
- 3083: 遥远的国度
- BZOJ 3083: 遥远的国度 树链剖分,处理树的换根
- BZOJ-3083 遥远的国度 树链剖分+分类讨论 or DFS序
- 【bzoj3083】【遥远的国度】【树链剖分】
- 关于导入jar包的问题
- 初次见对象
- 提速Magento通过修改.htaccess文件
- hdu3487 Splay
- C++中class、struct、union的区别
- BZOJ 3083 遥远的国度 树链剖分
- HDU 2546 - 饭卡
- 算法竞赛入门经典第一章习题答案
- 佛主保佑,永无BUG
- html和js图片上下居中的两种方法
- Magento模板及布局文件中引用静态块Static Block的方法
- QT的学习之路 2弹簧和按钮控件
- 1525. One Person "The Price is Right"
- 练习2