LOJ2319. 「NOIP2017」列队【线段树】
思路
神仙线段树
你考虑怎么样才能快速维护出答案
首先看看一条链怎么做?
首先很显然的思路是维护每个节点的是否出过队
然后对于重新入队的点
直接在后面暴力vector存一下就可以了
最核心的思路就是假设你已经知道了当前位置的点是什么编号,最后通过计算/查询来得出答案
然后不是链的情况其实就动态开点就可以了
因为有用的状态很少
然后就直接进行查询就可以了
//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 3e5 + 10;
const int LOG = 40;
int tot = 0, n, m, q, p;
int rt[N], ls[N * LOG], rs[N * LOG], siz[N * LOG];
vector<ll> v[N];
void insert(int &t, int l, int r, int pos) {
if (!t) t = ++tot;
++siz[t];
if (l == r) return;
int mid = (l + r) >> 1;
if (pos <= mid) insert(ls[t], l, mid, pos);
else insert(rs[t], mid + 1, r, pos);
}
int query(int t, int l, int r, int k) {
if (l == r) return l;
int mid = (l + r) >> 1, sizl = mid - l + 1 - siz[ls[t]];
if (k <= sizl) return query(ls[t], l, mid, k);
else return query(rs[t], mid + 1, r, k - sizl);
}
ll query_single_row(ll x, ll y) {
ll res = query(rt[0], 1, p, x);
insert(rt[0], 1, p, res);
ll id = (res <= n) ? res * m : v[0][res - n - 1];
v[0].push_back(y ? y : id);
return id;
}
ll query_single_line(ll x, ll y) {
ll res = query(rt[x], 1, p, y);
insert(rt[x], 1, p, res);
ll id = (res < m) ? (x - 1) * m + res : v[x][res - m];
v[x].push_back(query_single_row(x, id));
return id;
}
int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
Read(n), Read(m), Read(q);
p = max(n, m) + q;
fu(i, 1, q) {
int x, y; Read(x), Read(y);
if (y == m) Write(query_single_row(x, 0));
else Write(query_single_line(x, y));
putchar('\n');
}
return 0;
}