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;
}
原文地址:https://www.cnblogs.com/lovewhy/p/8575577.html