日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

D. Binary Spiders(思维+字典树)

發布時間:2023/12/16 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 D. Binary Spiders(思维+字典树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

D. Binary Spiders

[Link](Problem - D - Codeforces)

題意

給你nnn個數和一個kkk,問你最多選多少個數且滿足任意兩兩之間異或≥k\ge kk

思路

考慮怎么利用一些性質來統計方案,因為涉及⊕\oplus操作,我們轉化為二進制來考慮。

假設kkk的二進制最高位111為第mmm

對于任意兩個數a,ba,ba,b如果a,ba,ba,b二進制的m+1~29m+1\sim29m+129不同的話,必有a⊕b≥k(由異或性質a⊕b二進制的最高為一定比m高)a\oplus b\ge k(由異或性質a\oplus b二進制的最高為一定比m高)abk(abm),因此前綴不同的我們可以隨便選。

再來證明對于前綴相同(二進制位m+1~29m+1\sim29m+129相同)的數我們最多選兩個。

假設a,b,ca,b,ca,b,c前綴相同且a⊕b≥k且a⊕c≥ka\oplus b\ge k且a\oplus c\ge kabkack

則有a,b二進制的第二進制的第m位必為一個0一個1,a,c二進制的第二進制的第m位必為一個0一個1

b,cb,cb,c的二進制第mmm位相同且前綴相同因此b⊕c<kb\oplus c<kbc<k

因此由抽屜原理,前綴相同的最多選兩個。

由上面性質,我們將所有的數按照前綴分組,對于每組前綴我們看當前組是否存在一個數和他異或≥k\ge kk,有貢獻就是222,無貢獻就是111

找同組前面數和當前數異或最大值可以用字典樹維護復雜度為lognlognlogn,枚舉nnn,總復雜度為O(nlogn)O(nlogn)O(nlogn)

分組可以用mapmapmap,然后用迭代器遍歷。

特判kkk000的情況因為k==0k==0k==0,因為map只能存一個的下標,k==0k==0k==0時相同的數前綴相同,這些相同的數按剛才只能選兩,且下標不對。

Code

#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <set> #include <queue> #include <vector> #include <map> #include <bitset> #include <unordered_map> #include <cmath> #include <stack> #include <iomanip> #include <deque> #include <sstream> #define x first #define y second #define debug(x) cout<<#x<<":"<<x<<endl; using namespace std; typedef long double ld; typedef long long LL; typedef pair<int, int> PII; typedef pair<double, double> PDD; typedef unsigned long long ULL; const int N = 3e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7; const double eps = 1e-8, pi = acos(-1), inf = 1e20; #define tpyeinput int inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;} inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();} int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1}; int h[N], e[M], ne[M], w[M], idx; void add(int a, int b, int v = 0) {e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++; } int n, m, k; int a[N]; int tr[N * 30][2]; map<int, int> id; map<int, vector<int>> mp; vector<int> res; int bits(int x) {int res = 0;while (x) {x >>= 1;res ++;}return res; } void insert(int x) {int p = 0;for (int i = 30; i >= 0; i -- ) {int u = x >> i & 1;if (!tr[p][u]) tr[p][u] = ++ idx;p = tr[p][u];} } int query(int x) {int p = 0, res = 0;for (int i = 30; i >= 0; i -- ) {int u = x >> i & 1;if (!tr[p][!u]) {p = tr[p][u];res = res * 2 + u;}else {p = tr[p][!u];res = res * 2 + !u;}}return res; } int main() {ios::sync_with_stdio(false), cin.tie(0);cin >> n >> k;m = bits(k);for (int i = 1; i <= n; i ++ ) {cin >> a[i];int x = (a[i] >> m);mp[x].push_back(a[i]);id[a[i]] = i;}if (!k) {cout << n << endl;for (int i = 1; i <= n; i ++ ) cout << i << ' ';cout << endl;return 0;}map<int, vector<int>> ::iterator iter;for (iter = mp.begin(); iter != mp.end(); iter ++ ) {memset(tr, 0, sizeof (int)*2 * (idx + 1)), idx = 0;vector<int> ve = iter->second;int one = -1; bool ok = false;for (auto x : ve) {insert(x);int t = query(x);if ((t ^ x) >= k) {ok = true;res.push_back(id[t]);res.push_back(id[x]);break;}one = id[x];}if (one && !ok) res.push_back(one);}if (res.size() <= 1) cout << -1 << endl;else {cout << res.size() << endl;for (auto x : res) cout << x << ' ';cout << endl; }return 0; }

總結

以上是生活随笔為你收集整理的D. Binary Spiders(思维+字典树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。