HDU 5735 Born Slippy

来源:互联网 发布:dede免费源码站 编辑:程序博客网 时间:2024/05/29 18:57

给定一棵有根树,每个点都有一个权重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<<endlusing 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