牛客寒假演算法訓練營2 建通道

2022-05-18 06:27:05 字數 2461 閱讀 5642

輸出一行,乙個整數表示答案。
示例1

複製

2

1 2

複製

對於此題來說,拋去所有附加條件不管,是乙個mst問題。然鵝對於這種資料範圍,即使處理了重複的點再去建邊跑kruskal也是不科學的(將信將疑於是乎我們來思考別的解法。首先,毋庸置疑,肯定是去重,因為異或相同為0嘛,沒有花費當然要連咯。

其次,對於最小花費,只要全為奇數或偶數肯定是0嘛。

說到這裡肯定有很多小夥伴噴我,然鵝原題面就是這樣的,後來經過和出題人一頓bbox,他才把題面改了。。。

從此時起,一切就變了。lowbit的定義變成了最低非0位(一開始寫的是最低位),所以我們開始找最低的那個1在哪。

關於這個最低的非0位,需要滿足乙個條件,就是在這一位上,其他所有點的權值轉化為二進位制後的這一位,得異或出來乙個1。

怎樣才能異或出來乙個1呢,相信大家大一的時候上大計基課都學過異或的口訣,「相同為0,不同為1」,所以只要所有的點權值轉化為二進位制後,這一位有0又有1就好啦。

如何找到這一位呢,我們從最基礎的角度思考(因為我只會點基礎),利用&1的操作就可以辣,所以我們只要當找不到乙個位上有0又有1時(gay圈現狀),就把權值右移1位,直到找到某一位上有0又有1為止。

如果還有不太清楚的同學可以試試去掉注釋,輸出過程看看,手動寫寫就知道了。

1 #include 2

#define dbg(x) cout << #x << "=" << x << endl34

using

namespace

std;

5 typedef long

long

ll;6

const

int kmaxn = 3e5 + 7;7

8int

a[kmaxn];

9set

s[37

];10

int f[35][2

];11

12 templateinline void read(t &res)

1318

19namespace

_buff

27return ib == ie ? -1 : *ib++;28}

29}3031

intqread()

39if (c == '-'

) 43

for (; c >= '

0' && c <= '

9'; c =getc())

46return pos ? ret : -ret;47}

4849

intmain()

5059

/*60

printf("f[0][0]:%d f[0][1]:%d\n",f[0][0],f[0][1]);

61int d = s[0].size();

62for(set::const_iterator p = s[0].cbegin(); p != s[0].cend(); ++p)

65*/

66 ll ans = 0;67

for(int i = 0; i <= 30; ++i)

72for

(auto it : s[i])

76/*

77printf("f[%d][0]:%d f[%d][1]:%d\n",i,f[i][0],i,f[i][1]);

78int d1 = s[i].size();

79for(set::const_iterator p = s[i].cbegin(); p != s[i].cend(); ++p)

82*/83}

84 cout << ans <

85return0;

86 }

view code

牛客寒假演算法基礎演算法訓練營2

1 座與重修費 題目描述 期末考試結束了,座發現很多人掛了大物,只能等著第二年重修,還要交400元的重修費。座突然想起有個學長和他講過,如果學校哪一年缺錢了,那一年的大物試卷就會特別難。現在 座有了所有人的成績,座想知道如果所有掛科的人都在第二年重修,學校能賺多少重修費?掛科是指一門課的分數小於60...

牛客寒假演算法訓練營第二場 I建通道

首先,我們要建立的是乙個最小生成樹 跟最小生成樹其實沒關係 這些資料在位運算時有一些規律 1.兩個相同的數lowbit 結果為0,所以如果有兩個點的權值相同我們一定會讓他們兩個相連,由此,我們可以先對權值進行排序去重,去重後的權值個數是我們後面要計算的權值,那些相同的權值,因為我們要把它們連起來,並...

牛客寒假演算法基礎訓練營6

早知道這次題目這麼簡單就認真做了,最後一場沒心做,後面懶得想了,唉罪過罪過 1 煤氣灶 題目描述 小j開始打工,準備賺錢買煤氣灶。第一天,小j的工資為n元,之後每天他的工資都比前一天多d元。已知煤氣灶需要m元,求小j最少工作幾天才能買到煤氣灶。輸入描述 四個整數 n,m,d,x 分別表示小j第一天的...