• 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
    ",ans[i]);
    109     return 0;
    110 }
  • 相关阅读:
    最高效的无限级菜单生成方法
    MySQL性能优化的最佳20+条经验(转)
    Web应用中的轻量级消息队列
    Delphi Setlength 内存释放总结
    Delphi 的TSpeedButton按下和弹起效果
    Delphi存取图像完整解决方案
    delphi 开机自动运行代码
    有关时间限制使用和软件注册的设计(delphi)
    Linux环境thinkphp配置以及数据源驱动改动
    Dalvik和ART简单介绍
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8351635.html
Copyright © 2020-2023  润新知