【BZOJ2460】元素(線性基---(id,value)綁定,求id異或非0對應的最大value 和)

題目:


  給定n個礦石的編號和魔力值,讓你選出一些礦石,這些礦石的id異或起來不能是0,而且總的魔力值最大,輸出最大的魔力值

Input

第一行包含一個正整數N,表示礦石的種類數。
接下來 N行,每行兩個正整數Numberi 和 Magici,表示這種礦石的元素序號和魔力值。

對於全部的數據:N ≤ 1000,Numberi ≤ 10^18,Magici ≤ 10^4。

Output

僅包一行,一個整數:最大的魔力值

Sample Input

3
1 10
2 20
3 30

Sample Output

50

解題思路:


看到XOR一般就要想到線性基,這裏只需要用到最基礎的線性基即可,不需要求異或出來的第k小的數

一般的線性基模版每當p[j]已經有數時,a[i]^=p[j],直到a[i]可以填入,這樣的話實際上最後能填入的那個非零的a[i]是由多個原a[i]異或出來的。

將礦石的屬性存入結構體數組中,按照魔力值從大到小排序,從魔力值大的礦石開始遍歷,用其id構造行階梯矩陣,如果可以填入(最終異或得到的a[i].id不爲0),說明最初的a[i].id與之前選定的礦石中的部分礦石的a[i].id異或起來不爲0,將其value值加入結果中,且整個行階梯矩陣本身就線性無關的,異或起來非0。這樣根據貪心的思想,最終結果記錄的就是最大的魔力值。

ac代碼:


 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000+10;
const int max_base=60;
struct node{
    ll id;
    ll value;
    friend bool operator <(node a,node b)
    {
        return a.value>b.value;
    }
}a[maxn];
ll n,p[max_base+3];
ll solve()
{
    ll ans=0;
    for(int i=0;i<n;i++)
    {
        for(int j=max_base;j>=0;j--)
        {
            if(a[i].id>>j&1)
            {
                if(p[j])
                    a[i].id^=p[j];
                else
                {
                    p[j]=a[i].id;
                    break;
                }
            }
        }
        if(a[i].id)
            ans+=a[i].value;
    }
    return ans;
}
int main()
{
    scanf("%lld",&n);
    for(int i=0;i<n;i++)
        scanf("%lld %lld",&a[i].id,&a[i].value);
    sort(a,a+n);
    printf("%lld\n",solve());
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章