zoukankan      html  css  js  c++  java
  • luogu P4074 [WC2013]糖果公园

    传送门

    这种题显然要用树上莫队

    何为树上莫队?就是在树上跑莫队算法就是先把树分块,然后把询问离线,按照左端点所在块为第一关键字,右端点所在块为第二关键字,时间戳(如果有修改操作)为第三关键字排序,然后依次处理.树上莫队要每个点记录是否访问,移动端点时需要把移动前和移动后的点之间的路径上的点(除了上述两点的lca)的访问状态取反,算答案时单独对询问两端点的lca算贡献

    然后用莫队的那一套理论直接做就好了

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    
    using namespace std;
    const int N=100000+10;
    il int rd()
    {
      int x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int to[N<<1],nt[N<<1],hd[N],tot=1;
    il void add(int x,int y)
    {
      ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
      ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
    }
    int n,m,q,szm,mm[N],nm,a[N],b[N],ti,mdf[N][3];
    int fa[N],de[N],sz[N],son[N],top[N];
    LL v[N],w[N],na,an[N];
    int st[N],tp;
    void dfs1(int x)
    {
      sz[x]=1;
      int la=tp;
      for(int i=hd[x];i;i=nt[i])
        {
          int y=to[i];
          if(y==fa[x]) continue;
          fa[y]=x,de[y]=de[x]+1,dfs1(y),sz[x]+=sz[y];
          if(sz[son[x]]<sz[y]) son[x]=y;
          if(tp-la>=szm)
            {
              ++nm;
              while(tp!=la) mm[st[tp--]]=nm;
            }
        }
      st[++tp]=x;
    }
    void dfs2(int x,int ntp)
    {
      top[x]=ntp;
      if(son[x]) dfs2(son[x],ntp);
      for(int i=hd[x];i;i=nt[i])
        {
          int y=to[i];
          if(y==fa[x]||y==son[x]) continue;
          dfs2(y,y);
        }
    }
    il int glca(int x,int y)
    {
      while(top[x]!=top[y])
        {
          if(de[top[x]]<de[top[y]]) swap(x,y);
          x=fa[top[x]];
        }
      return de[x]<de[y]?x:y;
    }
    bool vis[N];
    il void ad(int ww){++b[ww],na+=v[ww]*w[b[ww]];}
    il void dl(int ww){na-=v[ww]*w[b[ww]],--b[ww];}
    il void cg(int x)
    {
      if(vis[x]) dl(a[x]);
      else ad(a[x]);
      vis[x]^=1;
    }
    il void mv(int x,int y)
    {
      if(de[x]<de[y]) swap(x,y);
      while(de[x]!=de[y]) cg(x),x=fa[x];
      while(x!=y) cg(x),x=fa[x],cg(y),y=fa[y];
    }
    struct qu
    {
      int l,r,t,id;
      bool operator < (const qu &bb) const {return mm[l]!=mm[bb.l]?mm[l]<mm[bb.l]:(mm[r]!=mm[bb.r]?mm[r]<mm[bb.r]:t<bb.t);}
    }qq[N];
    
    int main()
    {
      n=rd(),m=rd(),q=rd();
      szm=(int)pow(n,0.61);
      for(int i=1;i<=m;++i) v[i]=rd();
      for(int i=1;i<=n;++i) w[i]=rd();
      for(int i=1;i<n;++i) add(rd(),rd());
      dfs1(1);
      while(tp) mm[st[tp--]]=nm;
      dfs2(1,1);
      for(int i=1;i<=n;++i) a[i]=rd();
      for(int i=1;i<=q;++i)
        {
          int op=rd(),x=rd(),y=rd();
          if(op==1)
            {
              if(mm[x]>mm[y]) swap(x,y);
              qq[i-ti].l=x,qq[i-ti].r=y,qq[i-ti].t=ti,qq[i-ti].id=i-ti;
            }
          else mdf[++ti][0]=x,mdf[ti][1]=y;
        }
      sort(qq+1,qq+q-ti+1);
      for(int i=1,l=1,r=1,t=0;i<=q-ti;l=qq[i].l,r=qq[i].r,++i)
        {
          while(t<qq[i].t)
            {
              ++t;
              int xx=mdf[t][0],yy=mdf[t][1];mdf[t][2]=a[xx];
              if(vis[xx]) dl(a[xx]),ad(yy);
              a[xx]=yy;
            }
          while(t>qq[i].t)
            {
              int xx=mdf[t][0],yy=mdf[t][2];
              if(vis[xx]) dl(a[xx]),ad(yy);
              a[xx]=yy;
              --t;
            }
          mv(l,qq[i].l),mv(r,qq[i].r);
          int lca=glca(qq[i].l,qq[i].r);
          cg(lca),an[qq[i].id]=na,cg(lca);
        }
      for(int i=1;i<=q-ti;++i) printf("%lld
    ",an[i]);
      return 0;
    }
    
  • 相关阅读:
    vue脚手架搭建项目步骤(转载)
    使用css样式设置按钮禁用
    如何设置页面文本不可复制?
    System.IO.IOException:需要的特权不被客户端持有。
    vs中 git fetch与git pull的区别
    如何获取按钮开关选中的状态?
    Uncaught TypeError: XXX is not a function...
    解决bootstrap缩小布局会乱的问题,缩小一定程度后出现横向滚动条
    日期(年月日)与时间戳互转换
    Java中的Finally
  • 原文地址:https://www.cnblogs.com/smyjr/p/10059282.html
Copyright © 2011-2022 走看看