Qtree3

題目描述

給出N個點的一棵樹(N-1條邊),節點有白有黑,初始全爲白node

有兩種操做:ios

0 i : 改變某點的顏色(原來是黑的變白,原來是白的變黑)spa

1 v : 詢問1到v的路徑上的第一個黑點,若無,輸出-1code

輸入輸出格式

輸入格式:blog

第一行 N,Q,表示N個點和Q個操做ci

第二行到第N行N-1條無向邊get

再以後Q行,每行一個操做"0 i" 或者"1 v" (1 ≤ i, v ≤ N).string

輸出格式:io

對每一個1 v操做輸出結果ast

輸入輸出樣例

輸入樣例#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.

Solution

這題顯然是樹鏈剖分,先把dfs序處理出來,但線段樹存什麼呢?能夠發現,若以1爲根,進行dfs序,這樣1到每一個點之間的最先出現的黑點,顯然是dfs序最小值,這樣線段樹存最小值就好了,咱們還要把線段樹上的點映射回樹中結點。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll(x) (x*2)
#define rr(x) (x*2+1)
using namespace std;
struct Node
{
    int to,next;
}a[201001];
int len,last[200110],siz[201010],son[201100],dep[201001],fa[200010],yuan[200101];
int id[201010],cnt,n,sum[400101],top[400101],mn[400110];
void add(int a1,int a2)
{
    a[++len].to=a2;
    a[len].next=last[a1];
    last[a1]=len;
}
void dfs1(int x,int father)
{
    int mxson=-1;siz[x]=1;
    for(int i=last[x];i;i=a[i].next)
    {
        int to=a[i].to;
        if(to==father) continue;
        dep[to]=dep[x]+1;
        fa[to]=x;
        dfs1(to,x);
        siz[x]+=siz[to];
        if(siz[to]>mxson) son[x]=to,mxson=siz[to];
    }
}
void dfs2(int x,int topf)
{
    id[x]=++cnt;
    yuan[cnt]=x;
    top[x]=topf;
    if(!son[x]) return;
    dfs2(son[x],topf);
    for(int i=last[x];i;i=a[i].next)
    {
        int to=a[i].to;
        if(to==fa[x]||to==son[x]) continue;
        dfs2(to,to);
    }
}
void pushup(int node){mn[node]=min(mn[ll(node)],mn[rr(node)]);}
void gai(int node,int l,int r,int pos)
{
    if(l==r) {sum[node]^=1;if(sum[node]==1) mn[node]=l;else mn[node]=1e9;return;}
    int mid=(l+r)/2;
    if(pos<=mid) gai(ll(node),l,mid,pos);
    else gai(rr(node),mid+1,r,pos);
    pushup(node);
}
int cha(int node,int l,int r,int left,int right)
{
    if(l>=left&&r<=right) return mn[node];
    int mid=(l+r)/2,ans=1e9;
    if(left<=mid) ans=min(ans,cha(ll(node),l,mid,left,right));
    if(right>mid) ans=min(ans,cha(rr(node),mid+1,r,left,right));
    return ans;
}
int cha1(int x,int y)
{
    int ans=1e9;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=min(ans,cha(1,1,n,id[top[x]],id[x]));
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=min(ans,cha(1,1,n,id[x],id[y]));
    if(ans==1e9)
    return -1;
    return yuan[ans];
}
int main()
{   
    for(int i=0;i<=400000;i++)
    mn[i]=1e9;
    int q,x,y,opt;
    cin>>n>>q;
    for(int i=1;i<n;i++)
    scanf("%d%d",&x,&y),add(x,y),add(y,x);
    dep[1]=1;
    dfs1(1,0);
    dfs2(1,1);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&opt,&x);
        if(opt==0)
        gai(1,1,n,id[x]);
        else
        printf("%d\n",cha1(1,x));
    }
}

博主蒟蒻,能夠隨意轉載,但必須附上原文連接k-z-j

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息