• Wannafly挑战赛21 E 未来城市规划


    传送门

    题目中给的信息很难直接维护,但是可以考虑一条边对答案的贡献

    在以(x)为根的子树里,如果一条边(i)的权值为(w_i),这条边深度更深的端点为(to_i),那么这条边对这个子树的贡献为(w_i*size_x*(size_x-size_{to_i})),也就是这条边会被计算边两端点个数之积次

    那么一个子树的答案就是$$sum_{i(to_i在x子树里,to_i eq x)} w_isize_{to_i}(size_x-size_{to_i})$$

    即$$sum_{i(to_i在x子树里,to_i eq x)} w_isize_xsize_{to_i}-w_i{size_{to_i}}^2$$$$size_xsum_{i(to_i在x子树里,to_i eq x)} w_isize_{to_i}-w_i{size_{to_i}}^2$$

    然后把边权(w_i)保存在(to_i)上,维护(w_i*size_{to_i})(w_i*{size_{to_i}}^2)就是个板子题

    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define eps (1e-7)
    
    using namespace std;
    const int N=70000+10,M=50000+10,mod=2019;
    il LL rd()
    {
      re LL x=0,w=1;re 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;
    }
    il int max(int a,int b){return a>b?a:b;}
    il int min(int a,int b){return a<b?a:b;}
    int s1[N<<2],s2[N<<2],z1[N<<2],z2[N<<2],s[N<<2],lz[N<<2];
    
    #define lc (o<<1)
    #define rc ((o<<1)|1)
    #define mid ((l+r)>>1)
    il void psup(int o){s1[o]=(s1[lc]+s1[rc])%mod,s2[o]=(s2[lc]+s2[rc])%mod;}
    il void psdn(int o)
    {
      if(lz[o])
        {
          s1[lc]=(s1[lc]+z1[lc]*lz[o]%mod)%mod,s2[lc]=(s2[lc]+z2[lc]*lz[o]%mod)%mod,lz[lc]=(lz[lc]+lz[o])%mod;
          s1[rc]=(s1[rc]+z1[rc]*lz[o]%mod)%mod,s2[rc]=(s2[rc]+z2[rc]*lz[o]%mod)%mod,lz[rc]=(lz[rc]+lz[o])%mod;
          lz[o]=0;
        }
    }
    void modif(int o,int l,int r,int ll,int rr,int x)
    {
      if(ll<=l&&r<=rr)
        {
          s1[o]=(s1[o]+z1[o]*x%mod)%mod,s2[o]=(s2[o]+z2[o]*x%mod)%mod,lz[o]=(lz[o]+x)%mod;
          psdn(o);
          return;
        }
      psdn(o);
      if(ll<=mid) modif(lc,l,mid,ll,rr,x);
      if(rr>mid) modif(rc,mid+1,r,ll,rr,x);
      psup(o);
    }
    int quer1(int o,int l,int r,int ll,int rr)
    {
      if(ll<=l&&r<=rr) return s1[o];
      psdn(o);
      int an=0;
      if(ll<=mid) an+=quer1(lc,l,mid,ll,rr);
      if(rr>mid) an+=quer1(rc,mid+1,r,ll,rr);
      psup(o);
      return an%mod;
    }
    int quer2(int o,int l,int r,int ll,int rr)
    {
      if(ll<=l&&r<=rr) return s2[o];
      //psdn(o);
      int an=0;
      if(ll<=mid) an+=quer2(lc,l,mid,ll,rr);
      if(rr>mid) an+=quer2(rc,mid+1,r,ll,rr);
      //psup(o);
      return an%mod;
    }
    int to[M<<1],nt[M<<1],w[M<<1],hd[N],tot=1;
    il void add(int x,int y,int z)
    {
      ++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
    }
    int sz[M],son[M],de[M],fa[M],top[M],id[M],a[M],b[M],ti;
    void dfs1(int x)
    {
      sz[x]=1;
      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[y]>sz[son[x]]) son[x]=y;
        }
    }
    void dfs2(int x)
    {
      id[x]=++ti,b[ti]=x;
      if(son[x]) top[son[x]]=top[x],dfs2(son[x]);
      for(int i=hd[x];i;i=nt[i])
        {
          int y=to[i];
          if(/*y==fa[x]||*/y==son[x]) continue;
          top[y]=y;
          dfs2(y);
        }
    }
    void bui(int o,int l,int r)
    {
      if(l==r) {z1[o]=sz[b[l]]%mod,z2[o]=(z1[o]*z1[o])%mod,s1[o]=a[b[l]]*z1[o]%mod,s2[o]=a[b[l]]*z2[o]%mod;return;}
      bui(lc,l,mid),bui(rc,mid+1,r);
      psup(o);
      z1[o]=(z1[lc]+z1[rc])%mod,z2[o]=(z2[lc]+z2[rc])%mod;
    }
    int n,q,x,y,z;
    char cc[4];
    
    int main()
    {
      n=rd(),q=rd();
      for(int i=2;i<=n;i++)
        {
          fa[i]=rd(),a[i]=rd()%mod;
          add(fa[i],i,a[i]);
        }
      dfs1(1),top[1]=1,dfs2(1);
      bui(1,1,n);
      while(q--)
        {
          scanf("%s",cc);
          if(cc[0]=='I')
        	{
        	  x=rd(),y=rd(),z=rd()%mod;
        	  while(top[x]!=top[y])
        	    {
        	      if(de[top[x]]<de[top[y]]) swap(x,y);
        	      modif(1,1,n,id[top[x]],id[x],z);
        	      x=fa[top[x]];
        	    }
        	  if(de[x]>de[y]) swap(x,y);
        	  if(x!=y) modif(1,1,n,id[x]+1,id[y],z);
        	}
          else
        	{
        	  x=rd();
        	  if(sz[x]==1) puts("0"); 
        	  else printf("%d
    ",((sz[x]%mod*quer1(1,1,n,id[x]+1,id[x]+sz[x]-1))%mod-quer2(1,1,n,id[x]+1,id[x]+sz[x]-1)+mod)%mod);
        	}
        }
      return 0;
    }
    
    
  • 相关阅读:
    AppDelegate生命周期详解
    Python基础数据类型
    Linux入门基础
    mac命令节选
    如何在mac下安装android sdk
    Uiatomator2 初步探索
    Uiautumator2学习,Gradle部分
    软件测试基础方法总结
    monkey测试小结
    链表中环的入口结点
  • 原文地址:https://www.cnblogs.com/smyjr/p/9723672.html
Copyright © 2020-2023  润新知