zoukankan      html  css  js  c++  java
  • TJOI/HEOI2016树


    (n,Q1e5)

    线段树轻松A

    并查集离线做法

    先统计所有的点标记次数

    先一遍dfs,若标记,父亲为自己,否则为树上的父亲

    询问离线,倒序询问

    若查询,直接查并查集父亲

    否则减标记,若标记为0,则将并查集父亲设为树上父亲

    时间复杂度(O(nlogn))

    并查集直接路径压缩才是正确复杂度,因为并查集父亲方向均向上,且代表意思为祖先最近标记点,所以修改时不会错

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const int N=1e5+4;
    int n,Q,c[N],fa[N],uf[N],op[N],uu[N],ans[N];
    vector<int>e[N];
    void dfs(int x){
    	if(c[x])uf[x]=x;
    	else uf[x]=fa[x];
    	for(auto v:e[x]){
    		if(v==fa[x])continue;
    		fa[v]=x;
    		dfs(v);
    	}
    }
    int find(int x){return uf[x]==x?x:uf[x]=find(uf[x]);}
    char ch[4];
    int main(){
    	n=read();Q=read();
    	for(int i=1,u,v;i<n;i++){
    		u=read();v=read();
    		e[u].push_back(v);e[v].push_back(u);
    	}
    	c[1]=1;
    	for(int i=1;i<=Q;i++){
    		scanf("%s",ch);
    		op[i]=(ch[0]=='C');
    		uu[i]=read();
    		if(op[i])c[uu[i]]++;
    	}
    	dfs(1);
    	for(int i=Q;i;i--){
    		if(op[i]&&!(--c[uu[i]]))uf[uu[i]]=fa[uu[i]];
    		else ans[i]=find(uu[i]);
    	}
    	for(int i=1;i<=Q;i++)
    		if(!op[i])cout<<ans[i]<<"
    ";
    	return (0-0);
    }
    
  • 相关阅读:
    Docker学习笔记
    Docker学习笔记
    Docker学习笔记
    Docker学习笔记
    Docker学习笔记
    第二类斯特灵数学习笔记
    浅谈"n个球"和"m个盒子"之间的乱伦关系
    cf932E. Team Work(第二类斯特灵数 组合数)
    [vijos]lxhgww的奇思妙想(长链剖分)
    BZOJ2054: 疯狂的馒头(并查集)
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12736542.html
Copyright © 2011-2022 走看看