线性基

P4570 [BJWC2011] 元素

有两种属性 要求其中一种选出来线性无关(不能异或为0)前提下,另外一种属性加起来最大, 把第二种属性从大到小排个序, 能加就加。

感性理解一下,就是我们对于线性基每个位置我们都尽可能让第二种属性大的去占住,这样就可以保证第二种属性加起来最大

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
typedef long long ll; 

const int B = 60;

struct linear_basis {
    ll num[B + 1];
    bool insert(ll x) {
        for (int i = B - 1; i >= 0; i--) {
            if (x & (1ll << i)) {
                if (num[i] == 0) { num[i] = x; return true; }
                x ^= num[i];
            }
        }
        return false;
    }

    // x 异或一个子集的最小值
    // 若为 0 表示 x 可以被这个集合表示出来
    ll querymin(ll x) {
        for (int i = B - 1; i >= 0; i--) {
            x = min(x, x ^ num[i]);
        }
        return x;
    }

    ll querymax(ll x) {
        for (int i = B - 1; i >= 0; i--) {
            x = max(x, x ^ num[i]);
        }
        return x;
    }
};

linear_basis T; 

const int N = 1e3 + 100;

struct node {
    ll id;
    int v;
} a[N];

bool cmp(node x, node y) {
    return x.v > y.v;
}

void solve() {    
    int n; cin >> n;

    for (int i = 1; i <= n; i++) {
        ll id; cin >> id;
        int v; cin >> v;
        a[i] = {id, v};
    }

    sort(a + 1, a + 1 + n, cmp);

    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        auto [id, v] = a[i];
        if (T.insert(id)) ans += v;
    }
    cout << ans << endl;
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    // int T = 1; cin >> T;
    // while(T--) solve();
    solve();

    return 0;
}
View Code

 

posted @ 2024-01-16 13:50  zhujio  阅读(4)  评论(0编辑  收藏  举报