给定一棵有根树,每个点都有一个权重 wi ,对任意一点,从该点到根的路径上选出含该点的一部分点构成序列,使得序列中相邻元素进行给定位运算的结果尽可能的大,求最大值。
折半枚举
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cassert>
#include<ctime>
#include<bitset>
#include<queue>
#include<set>
#define inf (1<<30)
#define INF (1ll<<62)
#define prt(x) cout<<#x<<":"<<x<<" "
#define prtn(x) cout<<#x<<":"<<x<<endl
using namespace std;
typedef long long ll;
typedef unsigned int uint;
template<class T>void sc(T &x){
x=0;char c;int f=1;
while(c=getchar(),c<48)if(c=='-')f=-1;
do x=x*10+(c^48);
while(c=getchar(),c>47);
x*=f;
}
template<class T>void nt(T x){
if(!x)return;
nt(x/10);
putchar('0'+x%10);
}
template<class T>void pt(T x){
if(x<0)putchar('-'),x=-x;
if(!x)putchar('0');
else nt(x);
}
template<class T>inline void Max(T &x,T y){if(x<y)x=y;}
const int maxn=70000;
const int maxb=256;
struct Edge{
int to,nxt;
}e[maxn];
int last[maxn],ecnt;
void ins(int u,int v){
e[ecnt]=(Edge){v,last[u]};
last[u]=ecnt++;
}
char ch[10];
int calc(int x,int y){
if(ch[0]=='A')return x&y;
if(ch[0]=='X')return x^y;
if(ch[0]=='O')return x|y;
return 2333;
}
int n;
uint q[maxb][maxb],p[maxn][maxb];
int v[maxb],w[maxn];
ll ans;
const int mod=1e9+7;
void dfs(int x){
int A=w[x]>>8,B=w[x]&255;
uint res=0;
for(int i=0;i<maxb;i++)
if(v[i])Max(res,(calc(i,A)<<8)+q[i][B]);
ans=(ans+1ll*x*(res+w[x])%mod)%mod;
v[A]++;
for(int i=0;i<maxb;i++)p[x][i]=q[A][i],Max(q[A][i],res+calc(i,B));
for(int i=last[x];i!=-1;i=e[i].nxt)
dfs(e[i].to);
v[A]--;
for(int i=0;i<maxb;i++)q[A][i]=p[x][i];
}
void solve(){
sc(n);scanf("%s",ch);
for(int i=1;i<=n;i++)sc(w[i]);
memset(last,-1,n+1<<2);
ecnt=0;
for(int u,i=2;i<=n;i++)
sc(u),ins(u,i);
ans=0;
dfs(1);
pt(ans);putchar('\n');
}
int main(){
// freopen("pro.in","r",stdin);
// freopen("chk.out","w",stdout);
int cas;sc(cas);
while(cas--)solve();
return 0;
}