hdu 5735 Born Slippy 暴力

本文介绍了一道名为 BornSlippy 的 ACM 竞赛题目,并提供了详细的解题思路和代码实现。该题涉及树形结构上的动态规划算法,需要求解每个节点到根路径的最大权值和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Born Slippy

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5735

Description

Professor Zhang has a rooted tree, whose vertices are conveniently labeled by 1,2,...,n. And the i-th vertex is assigned with weight wi.

For each s∈{1,2,...,n}, Professor Zhang wants find a sequence of vertices v1,v2,...,vm such that:

1. v1=s and vi is the ancestor of vi−1 (1<i≤m).
2. the value f(s)=wv1+∑i=2mwvi opt wvi−1 is maximum. Operation x opt y denotes bitwise AND, OR or XOR operation of two numbers.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n and a string opt (2≤n≤216,opt∈{AND,OR,XOR}) -- the number of vertices and the operation. The second line contains n integers w1,w2,...,wn (0≤wi<216). The thrid line contain n−1 integers f2,f3,...,fn (1≤fi<i), where fi is the father of vertex i.

There are about 300 test cases and the sum of n in all the test cases is no more than 106.

Output

For each test case, output an integer S=(∑i=1ni⋅f(i)) mod (109+7).

Sample Input

3
5 AND
5 4 3 2 1
1 2 2 4
5 XOR
5 4 3 2 1
1 2 2 4
5 OR
5 4 3 2 1
1 2 2 4

Sample Output

91
139
195

Hint

题意

给你一棵树,树上点有点权,对于每个点,你需要找到到根的那条链上的一个子序列。

使得f[i] = w[v[i]] + sigma w[v[i]] opt w[v[i+1]] 最大。

然后输出sigma(if[i])%mod

题解:

不会正解,n^2dp非常简单,很容易就能想到

然后感觉这道题的数据比较难造,就直接暴力了,然后一发就过了。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 70000;
const int mod = 1e9+7;
long long dp[maxn],w[maxn];
int n;
vector<int>E[maxn];
string opt;
set<pair<long long,int> > S;
set<pair<long long,int> >::iterator it;
long long solve(long long x,long long y){
    if(opt=="XOR")return x^y;
    if(opt=="AND")return x&y;
    if(opt=="OR")return x|y;
}
void dfs(int x){
    if(S.size()!=0){
        int tot = 0;
        for(it = S.begin();it!=S.end()&&tot<100;it++,tot++){
            dp[x] = max(dp[x],-(it->first)+solve(w[it->second],w[x]));
        }
    }
    S.insert(make_pair(-dp[x],x));
    for(int i=0;i<E[x].size();i++){
        int v = E[x][i];
        dfs(v);
    }
    S.erase(make_pair(-dp[x],x));
}
void solve(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)E[i].clear(),dp[i]=0;
    cin>>opt;
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    for(int i=2;i<=n;i++){
        int a;scanf("%d",&a);
        E[a].push_back(i);
    }
    dfs(1);
    long long ans = 0;
    for(int i=1;i<=n;i++){
        ans = (ans+i*(dp[i]%mod+w[i]%mod)) % mod;
    }
    printf("%I64d\n",ans);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--)solve();
    return 0;
}

转载于:https://www.cnblogs.com/qscqesze/p/5692878.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值