标签:less 异或运算 scan 因此 初始 ++ 主席树 The include
题目中,共有两种操作,一种是将第k个数字+1000,0000,一种是求一个最小的、不等于ai(1 <= i <= r)的,且不小于k的数字。
注意 这个数字,可以不出现在array中
因为array中的数字各不相同,因此,不等于ai(1 <= i <= r),等价于 这个数字可能会出现在 ai(r + 1 <= i <= n)。
为什么是可能?因为由于第一种操作+1000,10000,会使得进行第一种操作的那个数字,无论如何都不会和ai重复(1000,0000 比 51,0000大太多了)。
所以,这个题,我们可以将主席树进行适当的修改,每次查找ai[r + 1, n]中,不小于k的最小数字。
由于本题中,array由1-n的n个数字组成,因此不用考虑数字的去重(unique),以及 离散化问题。
除了上面两种情况,还有一种情况,我们没考虑到,如果k = n (已经过异或运算),那么这个答案还有可能是 n + 1。
综上,答案一共有三种情况:
三个数字,求最小值即可
#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
int const maxn = 530000;
int const inf = 0x3f3f3f3f;
using namespace std;
int a[maxn], b[maxn];
int root[maxn << 5];//第几个版本的根节点编号
int lc[maxn << 5], rc[maxn << 5], sum[maxn << 5];
int sz;//节点个数
int n, m;
void build(int &rt, int l, int r) {
rt = ++sz;
if (l == r) return;
int mid = (l + r) >> 1;
build(lc[rt], l, mid);
build(rc[rt], mid + 1, r);
}
int update(int id, int l, int r, int pos) {
int _id = ++sz;
lc[_id] = lc[id], rc[_id] = rc[id], sum[_id] = sum[id] + 1;
if (l == r) return _id;
int mid = (r + l) >> 1;
if (pos <= mid)
lc[_id] = update(lc[id], l, mid, pos);
else
rc[_id] = update(rc[id], mid + 1, r, pos);
return _id;
}
//查询 不比k大的最小数字
int query(int p, int q, int l, int r, int k) {
if (l == r) return l;
int x1 = sum[lc[q]] - sum[lc[p]];
int x2 = sum[rc[q]] - sum[rc[p]];
int mid = (l + r) >> 1;
int ans = inf;
if (x1 > 0 && mid >= k)
ans = query(lc[p], lc[q], l, mid, k);
//这个if不能写为else,因为第一个if可能无法得到结果,返回inf
if(ans == inf && x2 > 0 && r >= k)
ans = query(rc[p], rc[q], mid + 1, r, k);
return ans;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
while (~scanf("%d %d", &n, &m)) {
sz = 0;
set<int> s;
int lastAns = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + n + 1);
build(root[0], 1, n);
for (int i = 1; i <= n; i++) {
int pos = lower_bound(b + 1, b + n + 1, a[i]) - b;
root[i] = update(root[i - 1], 1, n, pos);
}
while (m--) {
int l;
scanf("%d", &l);
if (l == 1) {
int pos = 1; // 随意初始化
scanf("%d", &pos);
pos ^= lastAns;
//cout << "pos = " << pos << endl;
s.insert(a[pos]);
}
else {
int l, k;
scanf("%d %d", &l, &k);
l ^= lastAns;
k ^= lastAns;
//cout << "l = " << l << "k = " << k << endl;
int ansPos = query(root[l - 1 + 1], root[n], 1, n, k);
lastAns = (ansPos == inf) ? inf : b[ansPos];
set<int>::iterator it = s.lower_bound(k);
//
if (it != s.end()) lastAns = min(lastAns, *it);
lastAns = min(lastAns, n + 1);
printf("%d\n", lastAns);
}
}
}
}
return 0;
hdoj6703 2019 CCPC网络选拔赛 1002 array
标签:less 异或运算 scan 因此 初始 ++ 主席树 The include
原文地址:https://www.cnblogs.com/woxiaosade/p/11422266.html