zoukankan      html  css  js  c++  java
  • 洛谷 P4116 Qtree3

    洛谷 P4116 Qtree3

    洛谷传送门

    题目描述

    给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白

    有两种操作:

    0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)

    1 v : 询问1到v的路径上的第一个黑点,若无,输出-1

    输入格式

    第一行 N,Q,表示N个点和Q个操作

    第二行到第N行N-1条无向边

    再之后Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).

    输出格式

    对每个1 v操作输出结果


    题解:

    对于树上路径的题,肯定要先往树剖上想一想。

    怎么做呢?

    我们需要思考,如何用一棵树的树剖序+线段树来维护“最早出现”的黑点。那么这个最早出现的定义是什么呢?就是越浅越早。

    ??等等,越浅越早?维护最小值?

    对!

    我们可以把黑点的权值就赋成它的树剖序,白点的权值就赋成正无穷。那么我们就可以把这个区间查询转化成区间最小值来处理啦!

    细节是树剖序、节点编号的转化。

    代码:

    #include<cstdio>
    #include<algorithm>
    #define lson pos<<1
    #define rson pos<<1|1
    using namespace std;
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int read()
    {
        int x=0,f=1;
        char ch=nc();
        while(ch<48||ch>57)
        {
            if(ch=='-')
                f=-1;
            ch=nc();
        }
        while(ch>=48&&ch<=57)
            x=x*10+ch-48,ch=nc();
       	return x*f;
    }
    const int maxn=1e5+10;
    const int INF=1e9;
    int n,q;
    int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];
    int cnt,deep[maxn],fa[maxn],size[maxn],son[maxn],top[maxn],id[maxn],fid[maxn];
    int tree[maxn<<2];
    void add(int x,int y)
    {
    	to[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    void dfs1(int x,int f)
    {
    	deep[x]=deep[f]+1;
    	fa[x]=f;
    	size[x]=1;
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(y==f)
    			continue;
    		dfs1(y,x);
    		size[x]+=size[y];
    		if(!son[x]||size[y]>size[son[x]])
    			son[x]=y;
    	}
    }
    void dfs2(int x,int t)
    {
    	top[x]=t;
    	id[x]=++cnt;
    	fid[cnt]=x;
    	if(!son[x])
    		return;
    	dfs2(son[x],t);
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(y==fa[x]||y==son[x])
    			continue;
    		dfs2(y,y);
    	}
    }
    void pushup(int pos)
    {
    	tree[pos]=min(tree[lson],tree[rson]);
    }
    void build(int pos,int l,int r)
    {
    	int mid=(l+r)>>1;
    	if(l==r)
    	{
    		tree[pos]=INF;
    		return;
    	}
    	build(lson,l,mid);
    	build(rson,mid+1,r);
    	pushup(pos);
    }
    void update(int pos,int l,int r,int x)
    {
    	int mid=(l+r)>>1;
    	if(l==r)
    	{
    		tree[pos]=(tree[pos]<INF)?INF:l;
    		return;
    	}
    	if(x<=mid)
    		update(lson,l,mid,x);
    	else
    		update(rson,mid+1,r,x);
    	pushup(pos);
    }
    int query(int pos,int l,int r,int x,int y)
    {
    	int ret=INF;
    	int mid=(l+r)>>1;
    	if(x<=l && r<=y)
    		return tree[pos];
    	if(x<=mid)
    		ret=min(ret,query(lson,l,mid,x,y));
    	if(y>mid)
    		ret=min(ret,query(rson,mid+1,r,x,y));
    	return ret;
    }
    int q_chain(int x,int y)
    {
    	int ret=INF;
    	while(top[x]!=top[y])
    	{
    		if(deep[top[x]]<deep[top[y]])
    			swap(x,y);
    		ret=min(ret,query(1,1,n,id[top[x]],id[x]));
    		x=fa[top[x]];
    	}
    	if(deep[x]<deep[y])
    		swap(x,y);
    	ret=min(ret,query(1,1,n,id[y],id[x]));
    	return (ret==INF)?-1:fid[ret];
    }
    int main()
    {
    	n=read();q=read();
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		x=read();y=read();
    		add(x,y);
    		add(y,x);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	build(1,1,n);
    	for(int i=1;i<=q;i++)
    	{
    		int opt,x;
    		opt=read();x=read();
    		if(!opt)
    			update(1,1,n,id[x]);
    		else
    			printf("%d
    ",q_chain(1,x));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Checking Types Against the Real World in TypeScript
    nexus pip proxy config
    go.rice 强大灵活的golang 静态资源嵌入包
    几个golang 静态资源嵌入包
    rpm 子包创建学习
    Rpm Creating Subpackages
    ava 类似jest snapshot 功能试用
    ava js 测试框架基本试用
    The Architectural Principles Behind Vrbo’s GraphQL Implementation
    graphql-compose graphql schema 生成工具集
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13852073.html
Copyright © 2011-2022 走看看