1. 程式人生 > >p4570 [BJWC2011]元素

p4570 [BJWC2011]元素

不難 ret code efi true const gist fin bit

題目描述-->p4570 [BJWC2011]元素

題目大意

給定一些礦石的編號與價值,我們想要得到最大的價值和,並且選定物品的編號異或之和不為0.

分析

線性基就不多bb了,來這裏->p3812 [模板]線性基

貪心

我們從小到大,選擇價值大的礦石,滿足異或之和不為零的條件,我們就可以加上它的貢獻.

因此我們需要用到sort對價值從小到大排序.

線性基.

這題線性基有什麽用?說實話開始我也沒想到

我們很容易想到.

如果某個礦石能被使用,那它的編號的二進制下某一位一定是已經出現過的礦石編號中不存在的.(這句話還是仔細研讀,應該不難理解,qwq.

這句話簡單來講.對於某一個編號x,我們檢驗其與之前已選編號時候異或起來為0.

(因為線性基進行插入元素的操作時,我們會對這個元素的大小進行削減是這麽說吧.)

因此不難證明用線性基維護是正確的.

因此我們對已經選入的礦石的編號維護線性基.(那這題就裸了.

如果滿足條件(異或之和不為0),我們就可以選擇它,加上它的價值.

------------------代碼-------------------

#include<bits/stdc++.h>
#define int long long
#define IL inline
#define RI register int
using namespace std;
int n,ans,p[64];
struct cod{int idx,w;}rock[1008];
IL bool ccp(const cod&a,const cod&b){return a.w>b.w;}
IL bool ins(int x)
{
    for(RI i=63;i>=0;i--)
    {
        if(x&(1LL<<i))
        {
            if(p[i])
                x^=p[i];//削減操作 
            else
            {
                p[i]=x;//如果之前選擇的編號的當前一位不存在,而我的存在. 
                return true;//即能選擇當前編號. 
            }
        }
    }
    return false;
}
main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(RI i=1;i<=n;i++)
        cin>>rock[i].idx>>rock[i].w;
    stable_sort(rock+1,rock+n+1,ccp);
    for(RI i=1;i<=n;i++)
        if(ins(rock[i].idx))
            ans+=rock[i].w;
    cout<<ans;
}

p4570 [BJWC2011]元素