Description
有一个长度为
n
n
n 的序列
A
=
(
A
1
,
A
2
,
⋯
,
A
n
)
A=(A_1,A_2,\cdots,A_n)
A=(A1,A2,⋯,An)。
有
m
m
m 次操作,每个操作格式如下:
1 x v
:将 A x A_x Ax 修改成 v v v。2 x
:将序列 A A A 冒泡排序,求出原先的 A x A_x Ax 排序后的位置,然后将 A A A 复原。
Analysis
修改次数不多,考虑从这入手。
先对
A
A
A 排序,并记录
t
i
t_i
ti 表示原先的
A
i
A_i
Ai 排序后的位置。
接下来可以发现,修改有序序列中的一个数后,可以通过前后冒泡各一次来保持有序。(因为不知道改小了还是改大了)
排完后,重新记录一遍
t
i
t_i
ti 即可。
另外,由于
A
A
A 已经排过序,所以实现时需要改
A
t
x
A_{t_x}
Atx 而不是
A
x
A_x
Ax。
关键代码:
// Read data from standard input.
vector<PII> a(n);
for(int i = 0; i < n; i++){
cin >> a[i].first;
a[i].second = i;
}
sort(a.begin(), a.end());
// a[i].first: The value of this element。
// a[i].second: After sorting, the position of a[i] in the original sequence.
// t[i] represents the position of a[i] before sorting in the sorted sequence `a`.
vector<int> t(n);
for(int i = 0; i < n; i++) t[a[i].second] = i;
// Modify
auto update = [&](int x, int v){
// Note that the sequence here has already been sorted,
// so it needs to be changed to a[t[x]] instead of a[x].
a[t[x]].first = v;
// Scan from back to front (becoming less).
for(int j = n - 1; j >= 1; j--)
if(a[j] < a[j - 1]) swap(a[j], a[j - 1]);
// Scan from front to back (becoming greater).
for(int j = 1; j < n; j++)
if(a[j] < a[j - 1]) swap(a[j], a[j - 1]);
for(int i = 0; i < n; i++) t[a[i].second] = i;
};
查询的话,从定义出发,易得答案就是 t i t_i ti。
Code
注:代码中,下标从 0 0 0 开始。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define int long long
typedef pair<int, int> PII;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector<PII> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i].first;
a[i].second = i;
}
sort(a.begin(), a.end());
vector<int> t(n);
for (int i = 0; i < n; i++) t[a[i].second] = i;
auto update = [&](int x, int v) {
a[t[x]].first = v;
for (int j = n - 1; j >= 1; j--)
if (a[j] < a[j - 1]) swap(a[j], a[j - 1]);
for (int j = 1; j < n; j++)
if (a[j] < a[j - 1]) swap(a[j], a[j - 1]);
for (int i = 0; i < n; i++) t[a[i].second] = i;
};
for (int i = 0, op, x, v; i < m; i++) {
cin >> op >> x;
x--;
if (op == 1) {
cin >> v;
update(x, v);
} else cout << t[x] + 1 << endl;
}
return 0;
}