- 题意:要求就是有 \(n <= 7e5\) 长度的序列,然后要求给 \(n\) 个操作,每次删除一个数,删除的是在当前序列中,讲前 \(po_i\) 个数移到后面后的序列中最前面的数。
- 题解:权值线段树求第 \(k\) 大,然后这个 \(k\) 是根据删除的位置,一次一次找到规律推出来。
- 代码:
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const ll N = 7e5 + 9;
struct segmentTree {
struct node {
int l, r, data, L, R;
}tr[N<<4];
void pushup(int p){tr[p].data = tr[tr[p].l].data + tr[tr[p].r].data;}
inline void build(int l, int r, int p) {
tr[p].l = p << 1;
tr[p].r = p << 1 | 1;
tr[p].L = l, tr[p].R = r;
if (l ==r){tr[p].data = 1;return;}
int mid = l + r >> 1;
build(l, mid, tr[p].l);
build(mid + 1, r, tr[p].r);
pushup(p);
return;
}
inline void add(int pos, int p, int num) {
//cout << tr[p].L << " " << tr[p].R << endl;
tr[p].data += num;
int mid = tr[p].L + tr[p].R >> 1;
if (tr[p].L == tr[p].R)return;
if (pos <= mid)
add(pos, tr[p].l, num);
else add(pos, tr[p].r, num);
}
inline int ask(int l, int r, int p, int k) {
int cnt = tr[tr[p].l].data;
//cout << l << " " << r << " " << cnt << endl;
if (l == r)return l;
int mid = l + r >> 1;
if (cnt >= k)return ask(l, mid, tr[p].l, k);
else return ask(mid + 1, r, tr[p].r, k-cnt);
}
}T;
signed main() {
int n;scanf("%d", &n);
T.build(1, n, 1);
int cnt = n;
int pos = 1;
for (int i = 1; i <= n; i ++) {
int res;
int x;scanf("%d", &x);
int q = (pos + x) % cnt;
if (q == 0)pos = q = cnt;
else pos = q;
res = T.ask(1, n, 1, q);
printf("%d\n", res);
T.add(res, 1, -1);
cnt--;
}
}