【比赛总结】百度之星复赛总结

本文提供三道算法竞赛题目的解题思路与实现方法,包括寻找权值和的最大最小值、求序列期望及处理and运算的并查集维护。

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

Problem #1: 没有兄弟的舞会 928/2446

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

寻找权值和最大和最小的点集,要求点集满足最多只有一对兄弟。

想法一:贪心,枚举每一个节点的子节点(让0的子节点为1),取最大最小值,对于子节点数大于等于2的取次小次大节点的最小最大值,最后加上即可.

const int maxn = 1e5+100;

vector<int>son[maxn];
ll a[maxn];

int n;
bool cmp(int x,int y){return a[x] < a[y];}

void Solve(){
    scanf("%d",&n);ll x;
    for(int i=0;i<=n;i++) son[i].clear();

    son[0].push_back(1);
    for(int i=2;i<=n;i++){
        scanf("%I64d",&x);
        son[x].push_back(i);
    }
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++) sort(son[i].begin(),son[i].end(),cmp);

    ll MAX = 0,MIN = 0,x1 = LINF, x2 = -LINF;
    for(int i=0;i<=n;i++){
        int sz = son[i].size();
        if(!sz) continue;

        MAX += max(a[son[i][sz-1]],0ll);
        MIN += min(a[son[i][0]],0ll);

        if(sz >= 2){
            x2 = max(x2, a[son[i][sz-2]]);
            x1 = min(x1, a[son[i][1]]);
        }
    }
    MAX = max(MAX, MAX + x2);
    MIN = min(MIN, MIN + x1);
    printf("%I64d %I64d\n",MAX, MIN);
}

想法二:树形DP,对于每一个节点,维护已有一队兄弟的状态得到的结果和尚未有一队兄弟的状态得到的结果,取最优值

Problem #2: 序列期望 545/1163

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

经典求期望,枚举上界,对于每一个上界可求一个等差数列,运用num(h)num(小于等于h)−numh1num(小于等于h−1)的数量来得到上界正好是hh的数量

const int maxn = 1e2+100;

ll ksm(ll x,ll n){
    ll res = 1ll;
    while(n){
        if(n&1) res = res * x % mod;
        x = x * x % mod;
        n /= 2;
    }
    return res % mod;
}

ll inv(ll n){
    return ksm(n, mod-2)%mod;
}

ll l[maxn],r[maxn],cnt[maxn];

ll SUM(ll l, ll r) {
    return (l+r) * (r-l+1) / 2 %mod;
}
ll work(ll i, ll x, ll type = 0) {
    if(l[i] > x-type) return 0;
    return SUM(x - min(x - type,r[i]) + 1, x - l[i] + 1);
}


void Solve(){
    int n;scanf("%d",&n);
    ll fenmu = 1;
    ll up = 0;
    for(int i=1;i<=n;i++){
        scanf("%I64d %I64d",&l[i],&r[i]);
        fenmu = ( fenmu * ( r[i] - l[i] + 1) ) % mod;
        up = max( up , r[i] );
    }
    ll res = 0ll,tem ;
    for(ll i = 1; i <= up; i++){
        cnt[n+1] = 1;
        for(ll j = n ; j >= 1 ; j --) {
            cnt[j] = cnt[j+1] * work(j,i) % mod;
        }
        tem = 1;
        for(ll j = 1 ; j <= n ; j ++) {
            if(i <= r[j] && i >= l[j]) {
                res = res + tem * cnt[j+1] %mod;
                res %= mod;
            }
            tem = tem * work(j,i,1) % mod;
            if(!tem)  break;
        }

    }
    res = res * inv(fenmu) % mod;
    res = (res % mod + mod) % mod;
    printf("%I64d\n", res);
}

Problem #3: 带劲的and和 791/2435

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

并查集维护一下连通性就行了,我总感觉数据给小了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值