• 【树上莫队】bzoj3757 苹果树


    学习这位神犇的:http://blog.csdn.net/jiangyuze831/article/details/41476865

    注意:

    ①排序时第一关键字是左端点所在块编号(块状树),第二关键字是右端点dfs序。

    ②维护的当前链不能包括lca(l,r),但最后要计算上lca(l,r)的答案。

    ③对l->l'/r->r'取反的时候也不能取反lca(l,l')/lca(r,r')。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define N 50001
    #define M 100001
    int n,m;
    int first[N],en,next[N<<1],dfsn[N],v[N<<1],fa[N],bel[N],dep[N],siz[N],cnt,top[N];
    int x,y,root,sz,col[N],Time[N],ans,anss[M];
    bool vis[N];
    struct ASK{int l,r,a,b,id;void Read(){scanf("%d%d%d%d",&l,&r,&a,&b);}}Q[M];
    bool operator < (const ASK &a,const ASK &b)
    {return bel[a.l]!=bel[b.l] ? bel[a.l]<bel[b.l] : dfsn[a.r]<dfsn[b.r];}
    void AddEdge(const int &U,const int &V)
    {
    	v[++en]=V;
    	next[en]=first[U];
    	first[U]=en;
    }
    void dfs(int cur)
    {
    	dfsn[cur]=++cnt;
    	for(int i=first[cur];i;i=next[i])
    	  if(v[i]!=fa[cur])
    	    {
    	      dep[v[i]]=dep[cur]+1;
              fa[v[i]]=cur;
              dfs(v[i]);
    	    }
    }
    void makeblock(int cur)
    {
        for(int i=first[cur];i;i=next[i])
          if(v[i]!=fa[cur])
            {
              if(siz[bel[cur]]<sz)
                {
                  ++siz[bel[cur]];
                  bel[v[i]]=bel[cur];
                  top[v[i]]=top[cur];
                }
              makeblock(v[i]);
            }
    }
    int QLCA(int U,int V)
    {
        while(U!=V)
          {
            if(top[U]==top[V])
              {
                if(dep[U]<dep[V])
    			  swap(U,V);
                U=fa[U];
              }
            else
              {
                if(dep[top[U]]<dep[top[V]])
    			  swap(U,V);
                U=fa[top[U]];
              }
          }
        return U;
    }
    void update(const int &Col,const int &op)
    {
    	Time[Col]+=op;
    	if(!Time[Col]) --ans;
    	else if(Time[Col]==1&&op==1) ++ans;
    }
    void Work(int U,int V,int lca)  
    {
    	while(U!=lca)
    	  {
            vis[U]^=1;
    	  	update(col[U],vis[U]?1:-1);
            U=fa[U];
    	  }
    	while(V!=lca)
    	  {
            vis[V]^=1;
    	  	update(col[V],vis[V]?1:-1);
            V=fa[V];
    	  }
    }  
    void Solve(const int &p)  
    {
        int lca=QLCA(Q[p].l,Q[p].r);
        if(p==1) Work(Q[p].l,Q[p].r,lca);
        else
          {
          	Work(Q[p-1].l,Q[p].l,QLCA(Q[p-1].l,Q[p].l));
          	Work(Q[p-1].r,Q[p].r,QLCA(Q[p-1].r,Q[p].r));
          }
        update(col[lca],1);
        anss[Q[p].id]=ans;
        if(Q[p].a!=Q[p].b)
          anss[Q[p].id]-=(Time[Q[p].a]&&Time[Q[p].b]);
        update(col[lca],-1);
    }  
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i) scanf("%d",&col[i]);
    	for(int i=1;i<=n;++i)
    	  {
    	  	scanf("%d%d",&x,&y);
    	  	if(!x) root=y;
    	  	else if(!y) root=x;
    	  	else
    	  	  {
    	  	  	AddEdge(x,y);
    	  	  	AddEdge(y,x);
    	  	  }
    	  }
    	dfs(root);
    	for(int i=1;i<=n;i++)
    	  {
    	  	siz[bel[i]=dfsn[i]]=1;
    	    top[i]=i;
    	  }
    	sz=(((int)sqrt(n))<<1);
    	makeblock(root);
    	for(int i=1;i<=m;++i) Q[i].Read(),Q[i].id=i;
    	sort(Q+1,Q+m+1);
    	for(int i=1;i<=m;++i) Solve(i);
    	for(int i=1;i<=m;++i) printf("%d
    ",anss[i]);
    	return 0;
    }
  • 相关阅读:
    C#编程总结 字符转码
    获取 苹果UDID 序列号
    SVN :This XML file does not appear to have any style information associated with it.
    oracle 实时查询最耗CPU资源的SQL语句
    Oracle 优化和性能调整
    weblogic管理脚本
    weblogic状态监控脚本
    oracle性能检测sql语句
    Oracle动态性能表-V$SESSION_WAIT,V$SESSION_EVENT
    linux HBA 卡驱动安装
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4248124.html
Copyright © 2020-2023  润新知