Qtree3(树剖!!!)

发布时间 2023-09-08 09:39:02作者: 是002呀

传送门

前言

今天可以说是重新学了一下树剖吧,悄咪咪的打题,看了好久,纪念一下

题目分析

题目很简单,就是一共两种操作:

  1. 0 x 把原来黑色的变成白色,白色的变成黑色
  2. 1 x 从 $1$ 到 $x$ 找到第一个黑子,如果没有就输出 -1

操作一很简单,直接更改就行,线段树上也是单点修改,记得给节点打上标记。操作二我的思路是,从 $x$ 开始,每次向上找它所在重链头到他的区间和,借此判断上面有没有黑子,如果有就暴力从重链头开始找找到第一个出现的黑子并退出,然后再把 $x$ 变成重链头的父亲并继续循环,知道 $x$ 变成 $1$ 为止,这里要加上一个特判,就是对于 $1$ 要特判其行不行,不然会出现一种情况就是 $1$ 恰好是重链头的父亲就直接退出了,这样的话 $1$ 就会略过(这个问题看了好久,不加就只会有 $57$ 分)。

code

#include<bits/stdc++.h>
#define int long long 
#define ls root<<1
#define rs root<<1|1
#define as (start+end)>>1

const int N=5000005;

using namespace std;

struct node{
    int to,next;
}edge[N];
int head[N],tot;
int n,q;
int tr[N];
int dep[N],siz[N],fa[N],son[N],top[N];
int id[N],back[N],cnt;
bool be[N];

void add(int x,int y){
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
void dfs1(int x,int f){
    dep[x]=dep[f]+1;
    siz[x]=1;
    fa[x]=f;
    for(int i=head[x];i;i=edge[i].next){
        int xx=edge[i].to;
        if(xx==f) continue;
        dfs1(xx,x);
        siz[x]+=siz[xx];
        if(!son[x] || siz[xx]>siz[son[x]]) son[x]=xx;
    }
}
void dfs2(int x,int tv){
    top[x]=tv;
    id[x]=++cnt;
    back[cnt]=x;
    if(!son[x]) return ;
    dfs2(son[x],tv);
    for(int i=head[x];i;i=edge[i].next){
        int xx=edge[i].to;
        if(xx==son[x] || xx==fa[x]) continue;
        dfs2(xx,xx);
    }
}
void pushup(int root){
    tr[root]=tr[ls]+tr[rs];
}
void updata(int root,int start,int end,int pos){
    if(start==end){
        tr[root]^=1;
        return ;
    }
    int mid=as;
    if(pos<=mid) updata(ls,start,mid,pos);
    else updata(rs,mid+1,end,pos);
    pushup(root);
}
int qurey(int root,int start,int end,int l,int r){
    if(start>=l && end<=r) return tr[root];
    int mid=as;
    int res=0;
    if(mid>=l) res+=qurey(ls,start,mid,l,r);
    if(mid<r) res+=qurey(rs,mid+1,end,l,r);
    return res;
}
signed main(){
    cin>>n>>q;
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        add(x,y),add(y,x);
    }
    dfs1(1,1);
    dfs2(1,1);
    while(q--){
        int num,x;
        cin>>num>>x;
        if(num==1){
            int output=-1;
            int flag=0;
            while(1){
                int res=qurey(1,1,cnt,id[top[x]],id[x]);
                if(res>=1){
                    flag=1;
                    for(int i=id[top[x]];i<=id[x];i++){
                        if(be[back[i]]){
                            output=back[i];
                            break;
                        }
                    }
                }
                x=fa[top[x]];
                if(x==1){
                    if(be[back[x]]) output=1,flag=1;
                    break;
                }
            }
            if(!flag) puts("-1");
            else cout<<output<<endl;
        }
        else{
            updata(1,1,cnt,id[x]);
            be[x]^=1;
        }
    }
    return 0;
}