• [BZOJ3083]遥远的国度


    bzoj
    luogu

    题意

    给你一棵树,每个点有点权,支持三种操作:
    1、换根。
    2、路径全部改成某一个数。
    3、查询子树最小值。

    sol

    (LCT?)naive了吧。
    考虑换根对子树形态的影响。对于原树中的父子关系而言(以(1)为根的树),当根不在询问点的子树中时,询问点的子树和在原树中的子树是相同的。
    当询问点和根重合时,显然答案就是整棵树的答案。
    当询问点是根的祖先(根在询问点的子树中)时,答案应该就是原树去掉根所在的询问点的那个儿子这棵子树的答案。
    所以直接树剖维护即可。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define ll long long
    ll gi()
    {
    	ll x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 2e5+5;
    int n,m,to[N<<1],nxt[N<<1],head[N],cnt,root;
    int fa[N],dep[N],sz[N],son[N],top[N],dfn[N],low[N],ref[N];
    ll val[N],t[N<<2],tag[N<<2];
    void link(int u,int v)
    {
    	to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    }
    void dfs1(int u,int f)
    {
    	fa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
    	for (int e=head[u];e;e=nxt[e])
    		if (to[e]!=f)
    		{
    			dfs1(to[e],u);
    			sz[u]+=sz[to[e]];
    			if (sz[to[e]]>sz[son[u]]) son[u]=to[e];
    		}
    }
    void dfs2(int u,int up)
    {
    	top[u]=up;dfn[u]=++cnt;ref[cnt]=u;
    	if (son[u]) dfs2(son[u],up);
    	for (int e=head[u];e;e=nxt[e])
    		if (to[e]!=fa[u]&&to[e]!=son[u])
    			dfs2(to[e],to[e]);
    	low[u]=cnt;
    }
    bool inside(int u,int v){return dfn[v]<=dfn[u]&&dfn[u]<=low[v];}
    int jump(int u,int v)
    {
    	int gg=u;
    	while (top[u]^top[v])
    		gg=top[u],u=fa[top[u]];
    	return u==v?gg:son[v];
    }
    void build(int x,int l,int r)
    {
    	if (l==r) {t[x]=val[ref[l]];return;}
    	int mid=l+r>>1;
    	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    	t[x]=min(t[x<<1],t[x<<1|1]);
    }
    void cover(int x,ll v){t[x]=tag[x]=v;}
    void pushdown(int x)
    {
    	if (tag[x])
    	{
    		cover(x<<1,tag[x]);cover(x<<1|1,tag[x]);
    		tag[x]=0;
    	}
    }
    void modify(int x,int l,int r,int ql,int qr,ll v)
    {
    	if (l>=ql&&r<=qr) {cover(x,v);return;}
    	pushdown(x);int mid=l+r>>1;
    	if (ql<=mid) modify(x<<1,l,mid,ql,qr,v);
    	if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr,v);
    	t[x]=min(t[x<<1],t[x<<1|1]);
    }
    ll query(int x,int l,int r,int ql,int qr)
    {
    	if (l>=ql&&r<=qr) return t[x];
    	pushdown(x);int mid=l+r>>1;
    	if (qr<=mid) return query(x<<1,l,mid,ql,qr);
    	if (ql>mid) return query(x<<1|1,mid+1,r,ql,qr);
    	return min(query(x<<1,l,mid,ql,qr),query(x<<1|1,mid+1,r,ql,qr));
    }
    int main()
    {
    	n=gi();m=gi();
    	for (int i=1;i<n;++i)
    	{
    		int u=gi(),v=gi();
    		link(u,v);link(v,u);
    	}
    	cnt=0;dfs1(1,0);dfs2(1,1);
    	for (int i=1;i<=n;++i) val[i]=gi();
    	build(1,1,n);root=gi();
    	while (m--)
    	{
    		int opt=gi();
    		if (opt==1) root=gi();
    		if (opt==2)
    		{
    			int u=gi(),v=gi();ll w=gi();
    			while (top[u]^top[v])
    			{
    				if (dep[top[u]]<dep[top[v]]) swap(u,v);
    				modify(1,1,n,dfn[top[u]],dfn[u],w);
    				u=fa[top[u]];
    			}
    			if (dep[u]>dep[v]) swap(u,v);
    			modify(1,1,n,dfn[u],dfn[v],w);
    		}
    		if (opt==3)
    		{
    			int x=gi();
    			if (root==x) printf("%lld
    ",t[1]);
    			else if (inside(root,x))
    			{
    				int gg=jump(root,x);ll ans=query(1,1,n,dfn[x],dfn[x]);
    				if (dfn[gg]>1) ans=min(ans,query(1,1,n,1,dfn[gg]-1));
    				if (low[gg]<n) ans=min(ans,query(1,1,n,low[gg]+1,n));
    				printf("%lld
    ",ans);
    			}
    			else printf("%lld
    ",query(1,1,n,dfn[x],low[x]));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    sql server 阻塞与锁
    JVM监控
    Java性能分析之线程栈详解与性能分析
    MySQL监控调优
    JVM(上)
    性能测试流程介绍
    性能测试分析调优思路
    监控分析——Web中间件
    Linux性能测试工具安装全集
    Java基础(二十)集合(2)Collection接口
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8808800.html
Copyright © 2020-2023  润新知