• 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操作输出结果

    输入输出样例

    输入样例#1: 复制
    9 8
    1 2
    1 3
    2 4
    2 9
    5 9
    7 9
    8 9
    6 8
    1 3
    0 8
    1 6
    1 7
    0 2
    1 9
    0 2
    1 9 
    输出样例#1: 复制
    -1
    8
    -1
    2
    -1

    说明

    For 1/3 of the test cases, N=5000, Q=400000.

    For 1/3 of the test cases, N=10000, Q=300000.

    For 1/3 of the test cases, N=100000, Q=100000.

    //记录每个点下面那段区间的黑色的深度最浅的点是谁
    //修改到叶子节点,直接修改,pushup的时候在左右儿子里取个最优的
    
    //两天没做有些生疏了
    //update的时候位置直接传的v,应该是node[v].s,
    //因为找的是v这个点在线段树中的位置
    //还要传一下v等于几
    //node[v].s是在线段树中的位置,v是要改的节点的标号 
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N=1e5+5;
    
    int n,m;
    int head[N],num_edge;
    struct Edge
    {
        int v,nxt;
    }edge[N<<1];
    struct NODE
    {
        int fa,son;
        int size,dep;
        int top;
        int s,t;
    }node[N];
    struct TREE
    {
        TREE *lson,*rson;
        int l,r,mid;
        int num,col;
    }tree[N<<2];
    
    typedef TREE* Tree;
    Tree Root,now_node=tree;
    
    inline int read()
    {
        char c=getchar();int num=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num;
    }
    
    inline void add_edge(int u,int v)
    {
        edge[++num_edge].v=v;
        edge[num_edge].nxt=head[u];
        head[u]=num_edge;
    }
    
    void dfs1(int u)
    {
        node[u].size=1;
        for(int i=head[u],v;i;i=edge[i].nxt)
        {
            v=edge[i].v;
            if(v==node[u].fa)
                continue;
            node[v].fa=u;
            node[v].dep=node[u].dep+1;
            dfs1(v);
            node[u].size+=node[v].size;
            if(node[v].size>node[node[u].son].size)
                node[u].son=v;
        }
    }
    
    int bound;
    void dfs2(int u,int top)
    {
        node[u].s=++bound;
        node[u].top=top;
        if(node[u].son)
        {
            dfs2(node[u].son,top);
            for(int i=head[u],v;i;i=edge[i].nxt)
            {
                v=edge[i].v;
                if(v==node[u].son||v==node[u].fa)
                    continue;
                dfs2(v,v);
            }
        }
        node[u].t=bound;
    }
    
    void build(Tree &root,int l,int r)
    {
        root=++now_node;
        root->l=l,root->r=r,root->mid=l+r>>1;
        if(l==r)
            return;
        build(root->lson,l,root->mid);
        build(root->rson,root->mid+1,r);
    }
    
    void better(Tree root)
    {
        if(node[root->lson->num].dep>node[root->rson->num].dep)
            root->num=root->rson->num;
        else
            root->num=root->lson->num;
    }
    
    void update(const Tree &root,int pos,int num)
    {
        if(root->l==root->r)
        {
            root->col^=1;
            if(root->col)
                root->num=num;
            else
                root->num=0;
            return;
        }
        if(pos<=root->mid)
            update(root->lson,pos,num);
        else
            update(root->rson,pos,num);
        better(root);
    }
    
    int query(const Tree &root,int l,int r)
    {
        if(root->l==l&&root->r==r)
            return root->num;
        if(r<=root->mid)
            return query(root->lson,l,r);
        else if(l>root->mid)
            return query(root->rson,l,r);
        else
        {
            int a=query(root->lson,l,root->mid),b=query(root->rson,root->mid+1,r);
            return node[a].dep>node[b].dep?b:a;
        }
    }
    
    inline int Query(int x,int y)
    {
        int fx=node[x].top,fy=node[y].top;
        int ans=0,tmp,dep=599518803;
        while(fx!=fy)
        {
            if(node[fx].dep>node[fy].dep)
            {
                tmp=query(Root,node[fx].s,node[x].s);
                if(dep>node[tmp].dep)
                    ans=tmp,dep=node[tmp].dep;
                x=node[fx].fa;
                fx=node[x].top;
            }
            else
            {
                tmp=query(Root,node[fy].s,node[y].s);
                if(dep>node[tmp].dep)
                    ans=tmp,dep=node[tmp].dep;
                y=node[fy].fa;
                fy=node[y].top;
            }
        }
        if(node[x].dep>node[y].dep)
        {
            tmp=query(Root,node[y].s,node[x].s);
            if(dep>node[tmp].dep)
                ans=tmp;
        }
        else
        {
            tmp=query(Root,node[x].s,node[y].s);
            if(dep>node[tmp].dep)
                ans=tmp;
        }
        return ans?ans:-1;
    }
    
    int u,v;
    int main()
    {
        node[0].dep=0x7fffffff;
        n=read(),m=read();
        for(int i=1;i<n;++i)
        {
            u=read(),v=read();
            add_edge(u,v);
            add_edge(v,u);
        }
        dfs1(1);
        dfs2(1,1);
        build(Root,1,n);
        int opt,v;
        for(int i=1;i<=m;++i)
        {
            opt=read(),v=read();
            if(opt==0)
                update(Root,node[v].s,v);
            else
            {
                printf("%d
    ",Query(1,v));
            }
        }
        return 0;
    }
  • 相关阅读:
    React项目(垃圾分类后台管理)
    React 学习笔记
    xml学习
    .NET Core部署Windows服务
    .NET 生成PDF流
    无线数传电台是什么
    电流电压采集模块如何进行数据传输的
    Spring5快乐教程(十)AspectJ注解实现AOP
    Spring5快乐教程(九)注解编程详解
    Spring5快乐教程(八)注解编程详解
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8575577.html
Copyright © 2020-2023  润新知