官方博客讲的很清楚:点击打开链接
在这里贴一下做树上可持久化的代码仅供参考。
[code]:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = (1<<16)+5;
const int sqrn = (1<<8)+5;
const int MOD = 1e9+7;
struct Block{
LL ds[sqrn];
void init(){
memset(ds,-1,sizeof(ds));
}
}A[maxn+sqrn];
int tot,Rt[maxn][sqrn];
struct Nod{
int b,next;
void init(int b,int next){
this->b=b;this->next=next;
}
}buf[maxn];
int n,E[maxn],len,w[maxn];
char op[5];
LL dp[maxn],ans;
void pre_process(){
tot = 0;
for(int i = 0;i < (1<<8);i++){
A[i].init();
Rt[0][i] = i;
tot++;
}
}
int opr(int a,int b){
return op[0]=='A'?(a&b):op[0]=='O'?(a|b):(a^b);
}
int update(int id,LL a,int b){
int new_id = tot++,i;
for(i = 0;i < (1<<8);i++){
A[new_id].ds[i] = max(A[id].ds[i],(a+opr(b,i)));
}
return new_id;
}
LL query(int vet,int w){
int i,fr,bk;
LL ans = 0;
fr = w>>8;bk = w - (fr<<8);
for(i = 0;i < (1<<8);i++){
if(A[Rt[vet][i]].ds[bk]==-1) continue;
ans = max(ans,A[Rt[vet][i]].ds[bk]+(opr(fr,i)<<8));
}
return ans;
}
void init(){
len = 0;tot = (1<<8);ans = 0;
memset(E,-1,(n+1)*sizeof(int));
}
void add_edge(int a,int b){
buf[len].init(b,E[a]);E[a]=len++;
}
void dfs(int u,int pre){
int i,v;
dp[u] = query(pre,w[u]);
ans = (ans+u*(dp[u]%MOD+w[u])%MOD)%MOD;
for(i = 0;i < (1<<8);i++) Rt[u][i] = Rt[pre][i];
Rt[u][w[u]>>8] = update(Rt[u][w[u]>>8],dp[u],w[u]-((w[u]>>8)<<8));
for(i = E[u];i != -1;i = buf[i].next){
v = buf[i].b;
dfs(v,u);
}
}
int main(){
int i,j,cas,u;
scanf("%d",&cas);
pre_process();
while(cas--){
scanf("%d%s",&n,op);
init();
for(i = 1;i <= n;i++) scanf("%d",&w[i]);
for(i = 2;i <= n;i++){
scanf("%d",&u);
add_edge(u,i);
}
dfs(1,0);
printf("%I64d\n",(ans+MOD)%MOD);
}
return 0;
}