HDU 5735 Born Slippy

给定一棵有根树,每个点都有一个权重 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值