[十二省联考2019]异或粽子
很裸的一道可持久化trie,只需要按照主席树的套路,每次求区间第k大的异或值,套路和NOI2010超级钢琴一样,不过打错下标wa了半天还是非常的真实。
另外,这个题不需要维护三元组,你只需要把优先队列开成存pair<ll, int>的就行了,ll放异或值,int放当前这个值属于哪个右端点,然后开一个rk数组存这个右端点已经取到rank几就行了,还算是送温暖。
//author Eterna #define Hello the_cruel_world! #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<utility> #include<cmath> #include<climits> #include<deque> #include<functional> #include<complex> #include<numeric> #include<unordered_map> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define Pi acos(-1.0) #define ABS(x) ((x) >= 0 ? (x) : (-(x))) #define pb(x) push_back(x) #define lowbit(x) (x & -x) #define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin) #define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout) #define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define outd(x) printf("%d\n", x) #define outld(x) printf("%lld\n", x) #define il inline #define ls(x) arr[x].child[0] #define rs(x) arr[x].child[1] using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; typedef pair<ll, int> pli; const int maxn = 5e5; const int INF = 0x7fffffff; const int mod = 1e9 + 7; const double eps = 1e-7; inline int read_int() { char c; int ret = 0, sgn = 1; do { c = getchar(); } while ((c < '0' || c > '9') && c != '-'); if (c == '-') sgn = -1; else ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); return sgn * ret; } inline ll read_ll() { char c; ll ret = 0, sgn = 1; do { c = getchar(); } while ((c < '0' || c > '9') && c != '-'); if (c == '-') sgn = -1; else ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); return sgn * ret; } struct node { int child[2], cnt; }arr[45 * maxn + 5]; int tot, root[maxn + 5], n, k, pos[maxn + 5]; ll coe[40], a[maxn + 5], res; priority_queue<pli> q; void Insert(int& now, int pre, ll v, int cnt = 32) { if (!now)now = ++tot; arr[now].cnt = arr[pre].cnt + 1; if (cnt < 0)return; int p = (v >> cnt) & 1ll; arr[now].child[p ^ 1] = arr[pre].child[p ^ 1]; Insert(arr[now].child[p], arr[pre].child[p], v, cnt - 1); } ll Query(int l, int r, int k, ll v, int cnt = 32) { if (cnt < 0)return 0; int p = (v >> cnt) & 1ll; int sum = arr[arr[r].child[p ^ 1]].cnt - arr[arr[l].child[p ^ 1]].cnt; if (sum >= k)return coe[cnt] + Query(arr[l].child[p ^ 1], arr[r].child[p ^ 1], k, v, cnt - 1); else return Query(arr[l].child[p], arr[r].child[p], k - sum, v, cnt - 1); } int main() { coe[0] = 1; for (int i = 1; i <= 35; ++i)coe[i] = 2ll * coe[i - 1]; n = read_int(), k = read_int(); for (int i = 1; i <= n; ++i) { a[i] = read_ll(); a[i] ^= a[i - 1]; Insert(root[i], root[i - 1], a[i - 1]); } for (int i = 1; i <= n; ++i) { ll now = Query(root[0], root[i], 1, a[i]); q.push(pli(now, i)); pos[i] = 1; } for (int i = 1; i <= k; ++i) { pli now = q.top(); q.pop(); res += now.first; if (pos[now.second] <= now.second) { ++pos[now.second]; ll u = Query(root[0], root[now.second], pos[now.second], a[now.second]); q.push(pli(u, now.second)); } } outld(res); //system("pause"); return 0; }
posted on 2019-04-07 22:35 Eterna_King 阅读(219) 评论(0) 编辑 收藏 举报