zoukankan      html  css  js  c++  java
  • 【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家

    裸题,树状数组区间修改+单点查询。当然要稍微讨论一下链的左右端点是否修改的情况咯。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define N 300001
    int en,v[N<<1],first[N],next[N<<1],n;
    void AddEdge(const int &U,const int &V)
    {
    	v[++en]=V;
    	next[en]=first[U];
    	first[U]=en;
    }
    int dep[N],siz[N],fa[N],son[N],top[N],Num[N],tot;
    void dfs(int U,int d)
    {
        dep[U]=d;
        siz[U]=1;
        for(int i=first[U];i;i=next[i])
          if(v[i]!=fa[U])
            {
              fa[v[i]]=U;
              dfs(v[i],d+1);
              siz[U]+=siz[v[i]];
              if(siz[v[i]]>siz[son[U]])
                son[U]=v[i];
            }
    }
    void dfs2(int U)
    {
        if(son[U])
          {
            top[son[U]]=top[U];
            Num[son[U]]=++tot;
            dfs2(son[U]);
          }
        for(int i=first[U];i;i=next[i])
          if(v[i]!=fa[U]&&v[i]!=son[U])
            {
              top[v[i]]=v[i];
              Num[v[i]]=++tot;
              dfs2(v[i]);
            }
    }
    int SIZ[N],TOP[N],sz;
    void dfs3(int U)
    {
        for(int i=first[U];i;i=next[i])
          if(v[i]!=fa[U])
            {
              if(SIZ[TOP[U]]<sz)
                {
                  TOP[v[i]]=TOP[U];
                  ++SIZ[TOP[U]];
                }
              dfs3(v[i]);
            }
    }
    int lca(int U,int V)
    {
        while(U!=V)
          {
            if(TOP[U]!=TOP[V])
              {
                if(dep[TOP[U]]<dep[TOP[V]])
                  swap(U,V);
                U=fa[TOP[U]];
              }
            else
              {
                if(dep[U]<dep[V])
                  swap(U,V);
                U=fa[U];
              }
          }
        return U;
    }
    int d[N];
    void add_node(int p,const int &v){for(;p<=n;p+=(p&(-p))) d[p]+=v;}
    void add_range(const int &L,const int &R){add_node(L,1);if(R!=n)add_node(R+1,-1);}
    int query(int p){int res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;}
    void update(int U,int V)
    {
    	int f1=top[U],f2=top[V];
    	while(f1!=f2)
    	  {
    	  	if(dep[f1]<dep[f2])
    	  	  {
    	  	  	swap(f1,f2);
    	  	  	swap(U,V);
    	  	  }
    	  	add_range(Num[f1],Num[U]);
    	  	U=fa[f1];
    	  	f1=top[U];
    	  }
    	if(dep[U]>dep[V])
    	  swap(U,V);
    	add_range(Num[U],Num[V]);
    }
    int cnt,LL[N],RR[N];
    void dfs4(int U)
    {
    	LL[U]=++cnt;
    	for(int i=first[U];i;i=next[i])
    	  if(v[i]!=fa[U])
    	    dfs4(v[i]);
    	RR[U]=cnt;
    }
    int xu[N];
    void work(const int &L,const int &R,const int &op)
    {
    	if(op==n-1)
    	  {
    	  	if(fa[L]==R||fa[R]==L) return;
    	  	int LCA=lca(L,R);
    	  	if(LCA==L)
    	  	  {
    	  	  	for(int i=first[L];i;i=next[i])
    	  	  	  if(v[i]!=fa[L]&&LL[R]>=LL[v[i]]&&LL[R]<=RR[v[i]])
    	  	    	{
    	  	    	  update(v[i],fa[R]);
    	  	      	  return;
    	  	    	}
    	  	  }
    	  	else if(LCA==R)
    	  	  {
    	  	  	for(int i=first[R];i;i=next[i])
    	  	  	  if(v[i]!=fa[R]&&LL[L]>=LL[v[i]]&&LL[L]<=RR[v[i]])
    	  	    	{
    	  	    	  update(fa[L],v[i]);
    	  	      	  return;
    	  	    	}
    	  	  }
    	  	else update(fa[L],fa[R]);
    	  	return;
    	  }
    	if(lca(L,R)==L)
    	  {
    	  	for(int i=first[L];i;i=next[i])
    	  	  if(v[i]!=fa[L]&&LL[R]>=LL[v[i]]&&LL[R]<=RR[v[i]])
    	  	    {
    	  	      update(v[i],R);
    	  	      return;
    	  	    }
    	  }
    	else update(fa[L],R);
    }
    int main()
    {
    	int A,B;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",&xu[i]);
    	for(int i=1;i<n;++i)
    	  {
    	  	scanf("%d%d",&A,&B);
    	  	AddEdge(A,B);
    	  	AddEdge(B,A);
    	  }
    	top[1]=1;
    	Num[1]=++tot;
    	dfs(1,1);
    	dfs2(1);
    	sz=sqrt(n); if(!sz) sz=1;
        for(int i=1;i<=n;i++)
          {
            SIZ[i]=1;
            TOP[i]=i;
          }
        dfs3(1);
    	dfs4(1);
    	if(n==2)
    	  {
    	  	work(xu[2],xu[1],0);
    	  	goto OUT;
    	  }
    	update(xu[1],xu[2]);
    	for(int i=2;i<n;++i)
    	  work(xu[i],xu[i+1],i);
    	OUT:for(int i=1;i<=n;++i)
    	  printf("%d
    ",query(Num[i]));
    	return 0;
    }
  • 相关阅读:
    Codeforces 876C Classroom Watch:枚举
    Codeforces 876B Divisiblity of Differences:数学【任意两数之差为k的倍数】
    BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成树
    BZOJ 3391 [Usaco2004 Dec]Tree Cutting网络破坏:dfs【无根树 节点分枝子树大小】
    markdown常用数学符号小结
    BZOJ3211花神游历各国-线段树&树状数组-(HDU4027同类型)
    一维二维树状数组写法总结
    hdu4352-XHXJ's LIS状压DP+数位DP
    常用Git命令以及出现的状况ing
    bitset简单用法
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4323411.html
Copyright © 2011-2022 走看看