• Spoj Query on a tree III


    题目描述

    给出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.

    (假装我是在spoj上做的一样hhh)

    贼裸的树剖+线段树,,,练手题(今天建模能力为0,全在码模板hhh)

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 100005
    #define pb push_back
    using namespace std;
    vector<int> g[maxn];
    int dfn[maxn],dy[maxn],pos;
    int siz[maxn],f[maxn],opt;
    int cl[maxn],n,m,son[maxn],dc=0;
    int sum[maxn<<2|1],mxp[maxn<<2|1];
    int le,ri;
    
    void dfs1(int x,int fa){
        f[x]=fa,siz[x]=1;
        int to;
        for(int i=g[x].size()-1;i>=0;i--){
            to=g[x][i];
            if(to==fa) continue;
            dfs1(to,x),siz[x]+=siz[to];
            if(!son[x]||siz[to]>siz[son[x]]) son[x]=to;
        }
    }
    
    void dfs2(int x,int tp){
        dfn[x]=++dc,dy[dc]=x,cl[x]=tp;
        if(son[x]) dfs2(son[x],tp);
        int to;
        for(int i=g[x].size()-1;i>=0;i--){
            to=g[x][i];
            if(to==f[x]||to==son[x]) continue;
            dfs2(to,to);
        }
    }
    
    void update(int o,int l,int r){
        if(l==r){
            sum[o]^=1;
            if(sum[o]) mxp[o]=dy[l];
            else mxp[o]=0;
            return;
        }
        
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
        if(le<=mid) update(lc,l,mid);
        else update(rc,mid+1,r);
        if(sum[lc]) mxp[o]=mxp[lc];
        else mxp[o]=mxp[rc];
        sum[o]=sum[lc]+sum[rc];
    }
    
    int query(int o,int l,int r){
        if(l>=le&&r<=ri) return mxp[o];
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1,an=0;
        if(le<=mid) an=query(lc,l,mid);
        if(!an&&ri>mid) an=query(rc,mid+1,r);
        return an;
    }
    
    inline void tolt(int x){
        le=dfn[x],update(1,1,n);
    }
    
    inline int answer(int x){
        int an=-1,po;
        while(x){
            le=dfn[cl[x]],ri=dfn[x];
            po=query(1,1,n);
            if(po) an=po;
            x=f[cl[x]];
        }
        return an;
    }
    
    int main(){
        int uu,vv;
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++){
            scanf("%d%d",&uu,&vv);
            g[uu].pb(vv),g[vv].pb(uu);
        }
        
        dfs1(1,0);
        dfs2(1,1);
        
        while(m--){
            scanf("%d%d",&opt,&pos);
            if(opt) printf("%d
    ",answer(pos));
            else tolt(pos);
        }
        
        return 0;
    }
  • 相关阅读:
    多线程刷题
    Spring Security的<form>表单的一些细节以及configure(HttpSecurity http)的配置
    Spring Security配置loginPage后,默认的表单登录请求接口也是这个
    一个留了两个星期的bug,基础忘光了
    连接数据库
    反射--笔记(第一篇)
    让图片左右移动
    Java注解
    HTTP协议
    使用servlet连接数据库删除数据
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8289832.html
Copyright © 2020-2023  润新知