BZOJ3757 苹果树

Posted 大奕哥&VANE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3757 苹果树相关的知识,希望对你有一定的参考价值。

一道挺好的树上莫队板子题,可惜存在版权无法提交了。

这里给出代码供大家参考,分块操作类似于王室联盟,转成序列后和普通莫队一样。

By:大奕哥

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e5+5;
  4 int d[N],fa[N][20],bel[N],size[N],dfn[N],col[N],ans[N],p[N],head[N];
  5 int n,m,sum,idx,cnt,B,num,top,s[N];
  6 bool v[N];
  7 struct node{
  8     int to,nex;
  9 }e[N<<1];
 10 void add(int x,int y)
 11 {
 12     e[++cnt].nex=head[x];e[cnt].to=y;head[x]=cnt;
 13 }
 14 struct quer{
 15     int x,y,a,b,id;
 16     bool operator<(const quer &b)const{
 17         return bel[x]<bel[b.x]||(bel[x]==bel[b.x]&&dfn[y]<dfn[b.y]);
 18     }
 19 }q[N];
 20 void dfs(int x)
 21 {
 22     dfn[x]=++idx;s[++top]=x;
 23     for(int i=1;i<=16;++i)
 24     fa[x][i]=fa[fa[x][i-1]][i-1];
 25     for(int i=head[x];i;i=e[i].nex)
 26     {
 27         int y=e[i].to;
 28         if(y==fa[x][0])continue;
 29         fa[y][0]=x;d[y]=d[x]+1;
 30         dfs(y);
 31         size[x]+=size[y];
 32         if(size[x]>=B)
 33         {
 34             num++;
 35             for(int k=1;k<=size[x];++k)
 36             bel[s[top--]]=num;
 37             size[x]=0;
 38         }
 39     }
 40     size[x]++;
 41 }
 42 int lca(int x,int y)
 43 {
 44     if(d[x]<d[y])swap(x,y);
 45     int tmp=d[x]-d[y];
 46     for(int i=0;i<=16;++i)
 47     if(tmp&(1<<i))x=fa[x][i];
 48     for(int i=16;i>=0;--i)
 49     {
 50         if(fa[x][i]!=fa[y][i])
 51         {
 52             x=fa[x][i];
 53             y=fa[y][i];
 54         }
 55     }
 56     return x==y?x:fa[x][0];
 57 }
 58 void reverse(int x)
 59 {
 60     if(!v[x]){v[x]=1;p[col[x]]++;if(p[col[x]]==1)sum++;}
 61     else {v[x]=0;p[col[x]]--;if(p[col[x]]==0)sum--;}
 62     return;
 63 }
 64 void solve(int x,int y)
 65 {
 66     while(x!=y)
 67     {    
 68         if(d[x]<d[y])swap(x,y);
 69         reverse(x);x=fa[x][0];
 70     }
 71     return;
 72 }
 73 int main()
 74 {
 75     scanf("%d%d",&n,&m);
 76     B=sqrt(n);int x,y,rt;
 77     for(int i=1;i<=n;++i)scanf("%d",&col[i]);
 78     for(int i=1;i<=n;++i)
 79     {
 80         scanf("%d%d",&x,&y);
 81         if(!x)rt=y;else if(!y)rt=x;
 82         else add(x,y),add(y,x);
 83     }
 84     dfs(rt);num++;
 85     while(top)bel[s[top--]]=num;
 86     for(int i=1;i<=m;++i)
 87     {
 88         scanf("%d%d",&q[i].x,&q[i].y);
 89         if(dfn[q[i].x]>dfn[q[i].y])swap(q[i].x,q[i].y);
 90         q[i].id=i;
 91         scanf("%d%d",&q[i].a,&q[i].b);
 92     }
 93     sort(q+1,q+1+m);
 94     int z=lca(q[1].x,q[1].y);
 95     solve(q[1].x,q[1].y);
 96     reverse(z);ans[q[1].id]=sum;
 97     if(p[q[1].a]&&p[q[1].b]&&q[1].a!=q[1].b)ans[q[1].id]--;
 98     reverse(z);
 99     for(int i=2;i<=m;++i)
100     {
101         int z=lca(q[i].x,q[i].y);
102         solve(q[i-1].x,q[i].x);
103         solve(q[i-1].y,q[i].y);
104         reverse(z);ans[q[i].id]=sum;
105         if(p[q[i].a]&&p[q[i].b]&&q[i].a!=q[i].b)ans[q[i].id]--;
106         reverse(z);
107     }
108     for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
109     return 0;
110 }

 

以上是关于BZOJ3757 苹果树的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj3757 苹果树

bzoj3757 苹果树

bzoj 3757 苹果树(树上莫队算法)

[bzoj4824][洛谷P3757][Cqoi2017]老C的键盘

BZOJ - 3757 树上莫队解决离线路径问题 & 学习心得

BZOJ5091 摘苹果 BZOJ2017年11月月赛 数学推导 逆元