# "Problem solving" AGC 001 F Wide Swap

Convert to inverse permutation (subscript and value exchange) and set it to \ (Q \), then the operation becomes that if \ (|Q_i-Q_{i-1}|\geq k \), you can exchange \ (Q_i,Q_{i-1} \), that is, for any \ (I < J, |Q_i-Q_j| < K \), \ (Q_i \) must always be in front of \ (Q_j \).

If the relative order of some elements is determined, any sequence satisfying this relative order can be obtained by constantly exchanging two adjacent elements.

Suppose you want to change \ (A \) into \ (B \), now re label the element in \ (A \) as its subscript in \ (B \). If it is the arrangement of \ (1\sim n \), you will get \ (B \). When it is not \ (1\sim n \), there must be adjacent reverse order pairs. Exchange the reverse order pairs. If there is no reverse order pair, it means that the exchange obtains \ (B \). Since we exchange reverse order pairs every time, and the relative order restrictions of \ (A \) and \ (B \) are the same, there will be no case that the exchange cannot be performed.

Now pretend to get these restrictions. If you want to minimize the dictionary order of the original sequence, you need to make the inversely arranged \ (1 \) as front as possible, on this basis \ (2 \) as front as possible, and then \ (3 \) as front as possible

If you only look at these restrictions, it is Dish making This problem is solved. After the DAG inverse graph is built, the one with the largest number is selected at the end of the sequence each time. But this problem is also right if you are building a map and put the smallest number at the front every time. Where is the little pink rabbit here If I give proof, I won't add anything to it(

Prove why it is right to build the inverse graph of DAG and then select the one with the largest number at the end of the sequence each time:

Consider that if the largest \ (x \) is not placed at the end of the sequence, but \ (x '\) is placed. Since \ (x \) has no restriction on moving backward, move \ (x \) to the end. In this way, the number of \ (< x \) after \ (x \) is moved forward by one position (at least one \ (x' \) will move forward by one position), which is better than the original, so any one is not \ (x \) The final scheme can be adjusted to a better scheme, so \ (x \) must be at the end of the sequence. After handling \ (x \), it becomes a sub problem. It is proved.

In implementation, a segment tree can be used to maintain the maximum value of the elements in the interval of the original sequence that have not been queued, so as to optimize the process of finding \ (0 \) degree points.

Time complexity \ (\ mathcal{O}(n\log n) \)

```#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#define pb emplace_back
#define mp std::make_pair
#define fi first
#define se second
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef std::vector<int> vi;
const ll mod = 998244353;
ll Add(ll x, ll y) { return (x+y>=mod) ? (x+y-mod) : (x+y); }
ll Mul(ll x, ll y) { return x * y % mod; }
ll Mod(ll x) { return x < 0 ? (x + mod) : (x >= mod ? (x-mod) : x); }
ll cadd(ll &x, ll y) { return x = (x+y>=mod) ? (x+y-mod) : (x+y); }
ll cmul(ll &x, ll y) { return x = x * y % mod; }
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template<typename T, typename... T2> T Max(T x, T2 ...y) { return Max(x, y...); }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template<typename T, typename... T2> T Min(T x, T2 ...y) { return Min(x, y...); }
template <typename T> T cmax(T &x, T y) { return x = x > y ? x : y; }
template <typename T> T cmin(T &x, T y) { return x = x < y ? x : y; }
template <typename T>
r = 0; bool w = 0; char ch = getchar();
while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
return r = w ? -r : r;
}
template<typename T1, typename... T2>
const int N = 500100;
const int inf = 0x7fffffff;
int n, k, a[N], b[N], id[N], ct;
#define ls tree[x].lson
#define rs tree[x].rson
#define tl tree[x].l
#define tr tree[x].r
int trnt;
struct Node {
int lson, rson, l, r, mx;
}tree[N << 1];
inline void pushup(int x) { tree[x].mx = Max(tree[ls].mx, tree[rs].mx); }
int build(int l, int r) {
int x = ++trnt; tl = l; tr = r;
if(l == r) {
tree[x].mx = a[l];
return x;
}
int mid = (l + r) >> 1;
ls = build(l, mid); rs = build(mid+1, r);
pushup(x);
return x;
}
int qmax(int x, int l, int r) {
if(tl >= l && tr <= r) return tree[x].mx;
int mid = (tl + tr) >> 1, s = -inf;
if(mid >= l) cmax(s, qmax(ls, l, r));
if(mid < r) cmax(s, qmax(rs, l, r));
pushup(x);
return s;
}
void modify(int x, int p, int v) {
if(tl == tr) {
tree[x].mx = v;
return ;
}
int mid = (tl + tr) >> 1;
if(mid >= p) modify(ls, p, v);
else modify(rs, p, v);
pushup(x);
}
#undef ls
#undef rs
#undef tl
#undef tr
std::priority_queue<int>q;
bool check(int i) { return qmax(1, i-k+1, i+k-1) == a[i]; }
signed main() {
for(int i = 1; i <= n; ++i) read(a[i]), id[a[i]] = i;
build(1, n);
for(int i = 1; i <= n; ++i)
if(check(i))
q.push(i);
ct = n;
while(!q.empty()) {
int x = q.top(); q.pop();
b[ct--] = x;
modify(1, x, -inf);
int t = 0;
t = qmax(1, x-k+1, x);
if(t != -inf && check(id[t]))
q.push(id[t]);
t = qmax(1, x, x+k-1);
if(t != -inf && check(id[t]))
q.push(id[t]);
}
for(int i = 1; i <= n; ++i) a[b[i]] = i;
for(int i = 1; i <= n; ++i) printf("%d\n", a[i]);
return 0;
}
```

Tags: data structure

Posted on Tue, 09 Nov 2021 18:27:06 -0500 by leena86