题解:P11165 [BalkanOI 2023] Super Tree
大半年前写的题。
借鉴了一下@yangjinhua 的思路。
一个比较显然的转化是,直接维护
考虑怎么更好地表示能量和超能量。记
不同位之间独立,下面只考虑某一位,假设当前询问
一是每位维护一个并查集,能找出下一个
二是虑暴力从左往右扫,如果当前位置已经是
然而现在还是会 MLE,把 dfs 换成非递归可以通过。
int n,m,id,idx,sm,tt,fa[N],dfn[N],nm[N],rk[N],sz[N];
ll a[N],b[N];
void QwQ() {
n=rd(),m=rd();
for(int i=2;i<=n;i++) fa[i]=rd()+1;
for(int i=1;i<=n;i++) a[i]=rdll(),sz[i]=1;
for(int i=2;i<=n;i++) a[i]&=a[fa[i]];
for(int i=n;i;i--) sz[fa[i]]+=sz[i];
for(int i=1;i<=n;i++) dfn[i]=nm[fa[i]]+1,b[dfn[i]]=a[i],rk[dfn[i]]=i,nm[fa[i]]+=sz[i],nm[i]=dfn[i];
for(int i=1;i<=n;i++) cadd(sm,b[i]%MOD),cadd(tt,vmul(b[i]%MOD,b[i]%MOD));
wr(vmul(sm,sm)," "),wr(vmul(vsub(vmul(sm,sm),tt),iv),"\n");
for(int u;m--;) {
u=rd()+1; ll x=rdll();
for(int k=0,j;k<60;k++) if(!(x>>k&1)) for(int i=dfn[u];i<dfn[u]+sz[u];i++) {
if(!(b[i]>>k&1)) {i+=sz[rk[i]]-1; continue;}
csub(sm,(1ll<<k)%MOD),csub(tt,vmul((1ll<<k)%MOD,vsub(b[i]*2%MOD,(1ll<<k)%MOD))),b[i]-=1ll<<k;
}
wr(vmul(sm,sm)," "),wr(vmul(vsub(vmul(sm,sm),tt),iv),"\n");
}
}