G. Function Query
题意
给你一个数组
input
5 6
3 5 1 2 4
0 2
1 1
2 3
3 2
4 2
5 8
output
2
3
2
1
4
-1
我们发现对于给定的
我们发现如果不存在
下标肯定不是盲目去找的,要想到找到某些具有特殊性质的下标。由于异或并不满足单调性,那么我们的特殊性质就很少了。我们应该想到需要找下标最小的点(最大也可以,下面以最小为例子),这样如果找到了满足
那么我们怎么去找呢?看到二进制,我们可以想到逐位比较。用字典树记录
code
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define X first
#define Y second
#define umap unordered_map
using ll = long long;
using ull = unsigned long long;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int maxn = 2e5 + 5, mod = 1e9 + 7, maxp = 31, inf = 1e9;
const ll INF = 1e18;
const double eps = 1e-6;
struct Trie {
vector<vector<int>> ch;
vector<int> z;
Trie(int n) {
ch.resize((n + 1) << 4);
z.resize((n + 1) << 4);
for (int i = 0; i < ((n + 1) << 4); i++) {
ch[i].resize(2);
}
}
int idx = 0;
void insert(int x, int id) {
int p = 0;
for (int j = 31; j >= 0; j--) {
int k = x >> j & 1;
if (!ch[p][k]) {
ch[p][k] = ++idx;
z[idx] = id;
}
p = ch[p][k];
}
}
int querym(int a, int b) {
int ans = -1;
int p = 0;
for (int j = 31; j >= 0; j--) {
bool f = false, g = false;
if (a >> j & 1) {
f = true;
}
if (b >> j & 1) {
g = true;
}
if (f && g) {
if (ch[p][1]) {
int res = z[ch[p][1]];
if (ans == -1) {
ans = res;
}
else {
ans = min(ans, res);
}
}
if (!ch[p][0]) {
return ans;
}
p = ch[p][0];
}
if (f && !g) {
if (!ch[p][1]) {
return ans;
}
p = ch[p][1];
}
if (!f && g) {
if (ch[p][0]) {
int res = z[ch[p][0]];
if (ans == -1) {
ans = res;
}
else {
ans = min(ans, res);
}
}
if (!ch[p][1]) {
return ans;
}
p = ch[p][1];
}
if (!f && !g) {
if (!ch[p][0]) {
return ans;
}
p = ch[p][0];
}
}
return ans;
}
int queryb(int a, int b) {
int ans = -1;
int p = 0;
for (int j = 31; j >= 0; j--) {
bool f = false, g = false;
if (a >> j & 1) {
f = true;
}
if (b >> j & 1) {
g = true;
}
if (f && g) {
if (!ch[p][0]) {
return ans;
}
p = ch[p][0];
}
if (f && !g) {
if (ch[p][0]) {
int res = z[ch[p][0]];
if (ans == -1) {
ans = res;
}
else {
ans = min(ans, res);
}
}
if (!ch[p][1]) {
return ans;
}
p = ch[p][1];
}
if (!f && g) {
if (!ch[p][1]) {
return ans;
}
p = ch[p][1];
}
if (!f && !g) {
if (ch[p][1]) {
int res = z[ch[p][1]];
if (ans == -1) {
ans = res;
}
else {
ans = min(ans, res);
}
}
if (!ch[p][0]) {
return ans;
}
p = ch[p][0];
}
}
return ans;
}
};
void solve() {
int n, q;
cin >> n >> q;
Trie tree(n + 1);
map<int, int> mp;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
tree.insert(x, i);
mp[x] = min(i, n - 1);
}
while (q--) {
int a, b;
cin >> a >> b;
if (mp.contains(a ^ b)) {
cout << mp[a ^ b] << endl;
continue;
}
int ans = max(tree.queryb(a, b), tree.querym(a, b));
if (ans <= 1) {
ans = -1;
}
else {
ans--;
}
cout << ans << endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt = 1;
// cin >> tt;
while (tt--) solve();
return 0;
}
A. Reverse Pairs Coloring
题意
给你一个长度为
input
9
5 9 1 8 2 6 4 7 3
output
5
可以对小数据画图分析。 比如题目所给样例,最后的方格是这样的:
xxxx.....
xxxx.xxx.
.........
.xxx.xx..
.........
..xx.....
..x......
..x......
.........
我们发现以下性质:
1. 对于第
2. 对于每个
于是我们可以模拟以下过程:
1. 对于每一个
2. 对于每一个
这样我们就模拟完了这个过程。但是目前还有一点问题,那就是怎么去记录每一行的染色情况呢?我们可以转换一下过程:只有一行。首先所有方格都染色。遍历到第
所以现在我们只需要维护一个数组了。由于是取前
code
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define X first
#define Y second
#define umap unordered_map
using ll = long long;
using ull = unsigned long long;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int maxn = 2e5 + 5, mod = 1e9 + 7, maxp = 31, inf = 1e9;
const ll INF = 1e18;
const double eps = 1e-6;
template<class T>
struct BIT {
vector<T> c;
int ub;
BIT() {}
BIT(int ub_) {
ub = ub_;
init();
}
void init() {
c.resize(ub + 1);
c.assign(ub + 1, 0);
}
int lowbit(int x) {
return x & -x;
}
void add(int pos, T val) {
if (pos <= 0) return;
while (pos <= ub) {
c[pos] += val;
pos += lowbit(pos);
}
}
T query(int pos) {
if (pos <= 0) return 0;
T res = 0;
while (pos) {
res += c[pos];
pos -= lowbit(pos);
}
return res;
}
T query(int l, int r) {
return query(r) - query(l - 1);
}
};
void solve() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<bool> vis(n + 2, true);
vis[0] = vis[n + 1] = false;
BIT<int> c(n);
c.add(1, 1);
ll ans = 0;
for (int i = 1; i <= n; i++) {
int x = a[i];
vis[x] = false;
if (c.query(x, x)) {
c.add(x, -1);
}
if (vis[x + 1]) {
c.add(x + 1, 1);
}
if (a[i] < a[i - 1]) continue;
ans += c.query(a[i - 1], a[i]);
}
cout << ans << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt = 1;
// cin >> tt;
while (tt--) solve();
return 0;
}