1 条题解

  • 0
    @ 2025-8-24 22:11:24

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar wind_whisper
    wind_whisper & KHIN Tie Tie /qq |鹏北海,凤朝阳,又携书剑路茫茫

    搬运于2025-08-24 22:11:24,当前版本为作者最后更新于2022-06-08 19:15:16,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    Foreword\text{Foreword}

    一道被洛谷遗忘的闹鬼题。
    第一眼:ddp?看一眼通过人数:怕不是道神题吧...
    开始使用大脑:...这暴力跳重链更新不就是 O(nlogn)O(n\log n) 吗...
    再看看通过人数...我一定是哪里假了...
    再想想我的做法...哪里假了啊...写写试试?

    提交...过了...
    ???
    连题解都没有??那我水一篇吧...

    Solution\text{Solution}

    总所周知,树剖每个节点到根的重链个数严格不超过 logn\log n 的。
    所以对于每个点维护其 chargexcharge_x 集合内所有点点权的乘积与加和,再对每个链头维护链上所有点点权的乘积与加和,修改的时候暴力维护即可。

    Code\text{Code}

    #include<bits/stdc++.h>
    #include<string>
    using namespace std;
    #define ll long long
    #define ull unsigned ll
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #define ok debug("OK\n")
    
    inline ll read() {
      ll x(0),f(1);char c=getchar();
      while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
      while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
      return x*f;
    }
    const int N=1e6+100;
    const int mod=99991;
    
    bool mem1;
    
    inline ll ksm(ll x,ll k){
      ll res(1);
      while(k){
        if(k&1) res=res*x%mod;
        x=x*x%mod;
        k>>=1;
      }
      return res;
    }
    
    int n,m,k;
    
    vector<int>e[N];
    ll mul[N],sum[N],cur[N],ori[N];
    ll top_mul[N],top_sum[N],ni[N];
    int top[N],fa[N],siz[N],hson[N];
    int a[N];
    void dfs1(int x,int f){
      fa[x]=f;
      siz[x]=1;
      for(int to:e[x]){
        if(to==f) continue;
        dfs1(to,x);
        siz[x]+=siz[to];
        if(siz[to]>siz[hson[x]]||(siz[to]==siz[hson[x]]&&to<hson[x])) hson[x]=to;
      }
      return;
    }
    bool tag[N];
    void dfs2(int x,int tp){
      top[x]=tp;
      mul[x]=1;
      if(x==top[x]) top_mul[x]=1;
      if(hson[x]) dfs2(hson[x],tp);
      for(int to:e[x]){
        if(to==hson[x]) continue;
        dfs2(to,to);
      }
      if(e[x].empty()) cur[x]=a[x],tag[x]=1;
      else cur[x]=a[x]?mul[x]:sum[x];
      if(!tag[x]) return;
      if(top[x]>1){
        mul[fa[top[x]]]=mul[fa[top[x]]]*cur[x]%mod;
        sum[fa[top[x]]]=(sum[fa[top[x]]]+cur[x])%mod;
        tag[fa[top[x]]]=1;
      }
      top_mul[top[x]]=top_mul[top[x]]*cur[x]%mod;
      top_sum[top[x]]=(top_sum[top[x]]+cur[x])%mod;
      //printf("x=%d cur=%lld\n",x,cur[x]);
      return;
    }
    inline void upd(int x){
      if(!tag[x]) return;
      ori[x]=cur[x];
      if(e[x].empty()) cur[x]=a[x];
      else cur[x]=a[x]?mul[x]:sum[x];
      top_mul[top[x]]=top_mul[top[x]]*ni[ori[x]]%mod;
      top_sum[top[x]]=(top_sum[top[x]]+mod-ori[x])%mod;
      top_mul[top[x]]=top_mul[top[x]]*cur[x]%mod;
      top_sum[top[x]]=(top_sum[top[x]]+cur[x])%mod;
    
      if(top[x]>1){
        mul[fa[top[x]]]=mul[fa[top[x]]]*ni[ori[x]]%mod;
        sum[fa[top[x]]]=(sum[fa[top[x]]]+mod-ori[x])%mod;
        mul[fa[top[x]]]=mul[fa[top[x]]]*cur[x]%mod;
        sum[fa[top[x]]]=(sum[fa[top[x]]]+cur[x])%mod;
        upd(fa[top[x]]);
      }
    }
    
    bool mem2;
    signed main() {
    #ifndef ONLINE_JUDGE
      freopen("a.in","r",stdin);
      freopen("a.out","w",stdout);
    #endif
      for(int i=1;i<mod;i++) ni[i]=ksm(i,mod-2);
      n=read();m=read();
      for(int i=2;i<=n;i++) e[read()].push_back(i);
      for(int i=1;i<=n;i++) a[i]=read();
      dfs1(1,0);
      dfs2(1,1);
      for(int i=1;i<=m;i++){
        int op=read(),x=read();
        if(op==1){
          int w=read();
          a[x]=w;
          upd(x);
        }
        else if(op==2){
          a[x]^=1;
          upd(x);
        }
        else printf("%lld %lld\n",top_sum[top[x]],top_mul[top[x]]);
      }
      return 0;
    }
    /*
      3 1
      2 3 3 1
      1 1
    */
    
    • 1

    信息

    ID
    4472
    时间
    1500ms
    内存
    128MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者