zoukankan      html  css  js  c++  java
  • 洛谷 P3979 遥远的国度 树链剖分

    题目描述

    题目传送门

    分析

    这道题的难点在于增加了换根操作

    如果对于每一次操作都重新剖一遍显然是不现实的

    我们不妨先以 (1) 为根节点进行树剖

    设当前的根节点为 (rt)

    如果我们要查询的节点是 (rt),直接输出全局最小值

    如果我们要查询的节点在 以 (1) 为根时 (rt) 的子树中

    那么以 (1) 为根或者以 (rt) 为根结果都是一样的

    如果我们要查询的节点不属于以上两种情况,也不在 (1)(rt) 的链上,在其他的支叉上

    (rt) 为根或是 (1) 为根还是没有影响,也直接查询

    要特殊处理的情况就是查询的节点在 (1)(rt) 的链上

    此时我们要找到在这条链上的要查询的节点的儿子节点

    要计算的就是除了该节点的子树以外所有节点的贡献

    要注意初始的最大值设大一点

    代码

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define rg register
    inline int read(){
    	rg int x=0,fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*fh;
    }
    const int maxn=1e5+5;
    int h[maxn],tot=1;
    struct asd{
    	int to,nxt;
    }b[maxn<<1];
    void ad(int aa,int bb){
    	b[tot].to=bb;
    	b[tot].nxt=h[aa];
    	h[aa]=tot++;
    }
    int fa[maxn][22],siz[maxn],son[maxn],dep[maxn],a[maxn];
    void dfs1(int now,int lat){
    	fa[now][0]=lat;
    	siz[now]=1;
    	dep[now]=dep[lat]+1;
    	for(rg int i=1;(1<<i)<=dep[now];i++){
    		fa[now][i]=fa[fa[now][i-1]][i-1];
    	}
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==lat) continue;
    		dfs1(u,now);
    		siz[now]+=siz[u];
    		if(son[now]==0 || siz[u]>siz[son[now]]){
    			son[now]=u;
    		}
    	}
    }
    int tp[maxn],dfnc,dfn[maxn],rk[maxn];
    void dfs2(int now,int top){
    	tp[now]=top;
    	dfn[now]=++dfnc;
    	rk[dfnc]=a[now];
    	if(son[now]) dfs2(son[now],top);
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==fa[now][0] || u==son[now]) continue;
    		dfs2(u,u);
    	}
    }
    int n,m,rt;
    struct trr{
    	int l,r,mmin,laz;
    	trr(){
    		laz=2147483647;
    		l=r=mmin=0;
    	}
    }tr[maxn<<2];
    void push_up(int da){
    	tr[da].mmin=std::min(tr[da<<1].mmin,tr[da<<1|1].mmin);
    }
    void push_down(int da){
    	if(tr[da].laz!=2147483647){
    		tr[da<<1].laz=tr[da].laz;
    		tr[da<<1|1].laz=tr[da].laz;
    		tr[da<<1].mmin=tr[da].laz;
    		tr[da<<1|1].mmin=tr[da].laz;
    		tr[da].laz=2147483647;
    	}
    }
    void build(int da,int l,int r){
    	tr[da].l=l,tr[da].r=r;
    	if(tr[da].l==tr[da].r){
    		tr[da].mmin=rk[l];
    		return;
    	}
    	rg int mids=(tr[da].l+tr[da].r)>>1;
    	build(da<<1,l,mids);
    	build(da<<1|1,mids+1,r);
    	push_up(da);
    }
    int cx(int da,int l,int r){
    	if(tr[da].l>=l && tr[da].r<=r){
    		return tr[da].mmin;
    	}
    	push_down(da);
    	rg int mids=(tr[da].l+tr[da].r)>>1,nans=2147483647;
    	if(l<=mids) nans=std::min(nans,cx(da<<1,l,r));
    	if(r>mids) nans=std::min(nans,cx(da<<1|1,l,r));
    	return nans;
    }
    void xg(int da,int l,int r,int val){
    	if(tr[da].l>=l && tr[da].r<=r){
    		tr[da].laz=val;
    		tr[da].mmin=val;
    		return;
    	}
    	push_down(da);
    	rg int mids=(tr[da].l+tr[da].r)>>1;
    	if(l<=mids) xg(da<<1,l,r,val);
    	if(r>mids) xg(da<<1|1,l,r,val);
    	push_up(da);
    }
    void xgtree(int xx,int yy,int val){
    	while(tp[xx]!=tp[yy]){
    		if(dep[tp[xx]]>dep[tp[yy]]) std::swap(xx,yy);
    		xg(1,dfn[tp[yy]],dfn[yy],val);
    		yy=fa[tp[yy]][0];
    	}
    	if(dep[xx]>dep[yy]) std::swap(xx,yy);
    	xg(1,dfn[xx],dfn[yy],val);
    }
    int get_lca(int xx,int yy){
    	while(tp[xx]!=tp[yy]){
    		if(dep[tp[xx]]>dep[tp[yy]]) std::swap(xx,yy);
    		yy=fa[tp[yy]][0];
    	}
    	if(dep[xx]>dep[yy]) std::swap(xx,yy);
    	return xx;
    }
    int zhao(int xx,int yy){
    	rg int now=xx;
    	for(rg int i=20;i>=0;i--){
    		if(dep[fa[now][i]]>=dep[yy]+1){
    			now=fa[now][i];
    		}
    	}
    	return now;
    }
    void cxtree(int xx){
    	rg int zx=get_lca(xx,rt),nans=2147483647;
    	if(xx==rt){
    		printf("%d
    ",tr[1].mmin);
    	} else if(zx==xx){
    		rg int now=zhao(rt,xx);
    		if(dfn[now]>=1) nans=std::min(nans,cx(1,1,dfn[now]-1));
    		if(dfn[now]+siz[now]<=n) nans=std::min(nans,cx(1,dfn[now]+siz[now],n));
    		printf("%d
    ",nans);
    	} else {	
    		printf("%d
    ",cx(1,dfn[xx],dfn[xx]+siz[xx]-1));
    	}
    }
    int main(){
    	memset(h,-1,sizeof(h));
    	n=read(),m=read();
    	rg int aa,bb,cc,dd;
    	for(rg int i=1;i<n;i++){
    		aa=read(),bb=read();
    		ad(aa,bb);
    		ad(bb,aa);
    	}
    	for(rg int i=1;i<=n;i++){
    		a[i]=read();
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	build(1,1,n);
    	rt=read();
    	for(rg int i=1;i<=m;i++){
    		aa=read();
    		if(aa==1){
    			rt=read();
    		} else if(aa==2){
    			bb=read(),cc=read(),dd=read();
    			xgtree(bb,cc,dd);
    		} else {
    			bb=read();
    			cxtree(bb);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    简单团队-爬虫豆瓣top250-项目总结
    团队-爬取豆瓣电影-最终程序
    软件工程课程总结
    课后作业-阅读任务-阅读提问-4
    20171201-构建之法:现代软件工程-阅读笔记》
    团队-爬取豆瓣电影Top250-简单团队一阶段互评
    团队编程项目--爬虫电影网站
    1213-构建之法:现代软件工程-阅读提问3
    简单团队-爬取豆瓣电影TOP250-项目进度
    团队-爬取豆瓣电影-项目总结
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/13997720.html
Copyright © 2011-2022 走看看