CF1856D More Wrong
CF1856D More Wrong
这道题目是一道关于使用分治算法求逆序对个数的问题。具体思路为:通过二分得到区间中两个部分的最大数位置,然后判断这两个数哪个更大,从而解决问题。
题意
有一个长度为 $n$ 的未知序列,询问 $l,r$ 可以通过花费 $r-l$ 个金币获取 $l$ 到 $r$ 之间逆序对的个数。你需要花费不多于 $5n^2$ 个金币来找到序列中最大数的个数。
思路
用分治来解决。如果询问的区间长度小于等于 $2$,很容易通过至多一次询问找到小区间中的最大数位置,否则二分后向下分治。这样,我们可以得到一个区间两个部分的最大数位置 $maxl,maxr$,问题变成如何判断这两个数哪个更大。
考虑区间 $[maxl,maxr]$,$maxl,maxr$ 之中对应数最大的那个显然也会是这个区间中的最大数。如果 $maxr$ 对应的数是区间中的最大数,那么区间 $[maxl,maxr]$ 中逆序对的数量会和 $[maxl,maxr-1]$ 中逆序对的数量相同。否则 $maxl$ 对应的数是区间中的最大数。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int n;
int query(int l, int r) {
if (l == r)
return 0;
cout << "? " << l << " " << r << endl;
cout.flush();
int x;
cin >> x;
return x;
}
int f(int l, int r) {
if (l == r)
return l;
if (l + 1 == r) {
int x = query(l, r);
if (x)
return l;
else
return r;
}
int maxl = f(l, (l + r) / 2), maxr = f((l + r) / 2 + 1, r);
if (query(maxl, maxr) == query(maxl, maxr - 1))
return maxr;
else
return maxl;
}
void solve() {
cin >> n;
int res = f(1, n);
cout << "! " << res << endl;
cout.flush();
}
This post is licensed under CC BY 4.0 by the author.